如果串行器實例在模型端的unique_together
約束失敗,返回True
時serializer.is_valid()
存在問題。Django REST框架:對串行器的唯一確認
有沒有辦法對我來說,在串行執行一個unique_together
約束指定?
如果串行器實例在模型端的unique_together
約束失敗,返回True
時serializer.is_valid()
存在問題。Django REST框架:對串行器的唯一確認
有沒有辦法對我來說,在串行執行一個unique_together
約束指定?
不幸的是,安德烈的回答是不是很完整,因爲它不會在更新的情況下工作。
相反,你會想要更多的東西一樣:
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和崗位工作。
是的,你可以做到這一點的串行的.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
您在模型中設置的唯一約束是用於創建數據庫約束,而不是用於驗證。
的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)
及以下串行和視圖集:
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_a
和foo_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."
]
}
我希望這導致對你有所幫助,即使這是一個有點老貼出的問題;-)
我需要這個覆蓋默認的消息。通過this解決了它。
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
class SomeSerializer(serializers.ModelSerializer):
"""
Demostrating How to Override DRF UniqueTogetherValidator Message
"""
class Meta:
model = Some
validators = [
serializers.UniqueTogetherValidator(
queryset=model.objects.all(),
fields=('field1', 'field2'),
message=_("Some custom message.")
)
]
Similarly you can specify fields
嗯,這是有點愚蠢的,這是非常不可能的,任何人,但我會犯這樣的錯誤,但我已經把同一型號有兩種串行類,因此我有這個問題
希望我的錯誤幫助別人!
有同樣的問題,並從這個答案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')
你可以包括有問題的模型? – Drewness