如何在django rest框架中验证集合中实例的唯一性
我有以下几种型号如何在django rest框架中验证集合中实例的唯一性,django,django-rest-framework,django-views,django-serializer,django-validation,Django,Django Rest Framework,Django Views,Django Serializer,Django Validation,我有以下几种型号 class ServerGroup(models.Model): name = models.SlugField(unique=True) factor = models.IntegerField() class ServerGroupMember(models.Model): class Meta: unique_together = ( ("server_group", "position"),
class ServerGroup(models.Model):
name = models.SlugField(unique=True)
factor = models.IntegerField()
class ServerGroupMember(models.Model):
class Meta:
unique_together = (
("server_group", "position"),
("server_group", "server"),
)
position = models.IntegerField()
server_group = models.ForeignKey(
"ServerGroup", related_name="servers", on_delete=models.CASCADE
)
server = models.ForeignKey("Server", on_delete=models.CASCADE)
服务器组有两个属性,name
和factor
,以及一组ServerGroupMember
对象。每个ServerGroupMember
对象都包含一个整数position
和对Server
对象的引用。对于给定的服务器组
而言,位置
必须是唯一的,对于给定的服务器组
而言,服务器
必须是唯一的。但是,在全局范围内,位置和服务器对象不必是唯一的,因为在2个服务器组中,位置1可能包含一个服务器,同一个服务器可能出现在多个服务器组中,但在同一个服务器组中不会出现多次
鉴于我有以下序列化程序,如何验证上述内容?该模型目前确实在数据库级别验证该条件,但如果我试图违反该条件,则将引发唯一约束错误。我想要的是能够在我的视图中检测到这一点,这样我就可以在它有机会命中数据库并引发异常之前返回适当的验证错误消息响应
class ServerGroupMemberSerializer(serializers.ModelSerializer):
class Meta:
model = models.ServerGroupMember
fields = ("position", "server")
server = serializers.SlugRelatedField(
slug_name="name", queryset=models.Server.objects.all()
)
class SrvereGroupSerializer(serializers.ModelSerializer):
class Meta:
model = models.ServerrGroup
fields = ("name", "factor", "servers")
servers = ServerGroupMemberSerializer(many=True, required=False)
def create(self, validated_data): ...
def update(self, validated_data): ...
您可以在覆盖模型中的
clean()
方法时检查验证,也可以在serializers.py
中进行验证。
此外,验证只涉及而不是ForeignKey
字段,因为您不能将ServerGroupMember
member两次添加到ServerGroup
server\u测试中
class ServerGroupMember(models.Model):
class Meta:
unique_together = (
("server_group", "position"),
("server_group", "server"),
)
position = models.IntegerField()
server_group = models.ForeignKey(
"ServerGroup", related_name="servers", on_delete=models.CASCADE
)
server = models.ForeignKey("Server", on_delete=models.CASCADE)
def clean(self):
super().clean()
if self.position in ServerGroup.server_group_set.all().values_list('position', flat=True):
raise ValidationError(f"Position {self.position} already exists for ServerGroup {self.server_group.name}")
我想出了一种方法,但仍然好奇这是否是最好的方法。这对于创建新的
ServerGroupMember
实例似乎很有效。虽然不确定它是否也适用于更新案例,但仍有待尝试
在视图中,在实例化序列化程序时,我传递给序列化程序的构造函数,一个包含ServerGroup
名称的上下文对象。例如
def post(self, request: Request, name: str, format=None) -> Response:
server_group = self.get_object() # defined elsewhere
serializer = serializers.ServerGroupMemberSerializer(
data=request.data, context={"server_group": server_group.name}
)
...
然后在ServerGroupMemberSerializer
中,我添加了字段级验证器,例如
def validate_position(self, value):
server_group = self.context.get("server_group")
try:
models.ServerGroupMember.objects.get(
server_group__name=server_group, position=position
)
except models.ServerGroupMember.DoesNotExist:
return value
raise serializers.ValidationError(
f"A server group member with position {position} already exists"
)
def validate_server(self, value):
... # Follow same pattern as above