Django REST框架:序列化器上的Unique_together验证

8fq7wneg  于 2023-10-21  发布在  Go
关注(0)|答案(6)|浏览(128)

如果序列化器示例在模型端的unique_together约束失败,则serializer.is_valid()返回True
有没有一种方法可以让我在序列化器中指定强制unique_together约束?

sh7euo9m

sh7euo9m1#

ModelSerializer类内置了这个功能,至少在djangorestframework>=3.0.0中是这样的,但是如果你使用的serializer不包括受unique_together约束影响的 * 所有 * 字段,那么当保存一个违反它的示例时,你会得到一个IntegrityError。例如,使用以下模型:

class Foo(models.Model):
    class Meta:
        unique_together = ('foo_a', 'foo_b')

    a = models.TextField(blank=True)
    b = models.TextField(blank=True)
    foo_a = models.IntegerField()
    foo_b = models.IntegerField(default=2)

以及以下序列化器和ViewSet:

class FooSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Foo
        fields = ('a', 'b', 'foo_a')

class FooViewSet(viewsets.ModelViewSet):
    queryset = models.Foo.objects.all()
    serializer_class = FooSerializer

routes = routers.DefaultRouter()
routes.register(r'foo', FooViewSet)

如果您尝试保存两个示例,并使用相同的foo_afoo_b设置,您将得到一个IntegrityError。但是,如果我们像这样修改序列化器:

class FooSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Foo
        fields = ('a', 'b', 'foo_a', 'foo_b')

然后你会得到一个正确的HTTP 400 BAD REQUEST状态码,以及响应正文中相应的JSON描述性消息:

HTTP 400 BAD REQUEST
Content-Type: application/json
Vary: Accept
Allow: GET, POST, HEAD, OPTIONS

{
    "non_field_errors": [
        "The fields foo_a, foo_b must make a unique set."
    ]
}

我希望这个结果对你有帮助,即使这是一个有点老的问题;- )

jv2fixgn

jv2fixgn2#

我需要这个来覆盖默认消息。用this解决。

from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, validators

class SomeSerializer(serializers.ModelSerializer):
  """
  Demostrating How to Override DRF UniqueTogetherValidator Message
  """

    class Meta:
        model = Some
        validators = [
            validators.UniqueTogetherValidator(
                queryset=model.objects.all(),
                fields=('field1', 'field2'),
                message=_("Some custom message.")
            )
        ]

同样,您可以指定字段。

e3bfsja2

e3bfsja23#

不幸的是,Andreas的答案并不完全,因为它在更新的情况下不起作用。
相反,你会想要一些更像:

def validate(self, attrs):
    field1 = attrs.get('field1', self.object.field1)
    field2 = attrs.get('field2', self.object.field2)

    try:
        obj = Model.objects.get(field1=field1, field2=field2)
    except StateWithholdingForm.DoesNotExist:
        return attrs
    if self.object and obj.id == self.object.id:
        return attrs
    else:
        raise serializers.ValidationError('field1 with field2 already exists')

这将适用于PUT、PATCH和POST。

yrefmtwq

yrefmtwq4#

是的,你可以在序列化器的.validate()方法中完成。

def validate(self, attrs):
    try:
        Model.objects.get(field1=attrs['field1'], field2=attrs['field2'])
    except Model.DoesNotExist:
        pass
    else:
        raise serializers.ValidationError('field1 with field2 already exists')

    return attrs

您在模型中设置的唯一约束是用于创建数据库约束,而不是用于验证。

yeotifhr

yeotifhr5#

有同样的问题,从这个答案https://stackoverflow.com/a/26027788/6473175我能够让它工作,但不得不使用self.instance而不是self.object

def validate(self, data):
    field1 = data.get('field1',None)
    field2 = data.get('field2',None)

    try:
        obj = self.Meta.model.objects.get(field1=field1, field2=field2)
    except self.Meta.model.DoesNotExist:
        return data
    if self.instance and obj.id == self.instance.id:
        return data
    else:
        raise serializers.ValidationError('custom error message')
hgtggwj0

hgtggwj06#

这有点愚蠢,除了我之外,其他人都不太可能犯这个错误,但是我把同一个模型放在两个序列化器类中,结果我遇到了这个问题
希望我的错误能帮助到别人!

相关问题