2014-03-24 34 views

回答

5

不幸的是,安德烈的回答是不是很完整,因爲它不會在更新的情況下工作。

相反,你會想要更多的東西一樣:

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和崗位工作。

+0

嗯有趣。我認爲如果你添加'.exists()'而不是直接獲取,你還可以使它更有效率?不知道沒有驗證ID的後果是什麼 – fangsterr

+1

@fangsterr你是對的,你可以做一些事情:'objects.filter(field1 = field1,field2 = field2).exists()'如果你'重新更新一個對象,匹配的對象將存在 - 你正在更新的那個,這就是id比較的意義。 – JeffS

2

是的,你可以做到這一點的串行的.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 

您在模型中設置的唯一約束是用於創建數據庫約束,而不是用於驗證。

9

的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_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." 
    ] 
} 

我希望這導致對你有所幫助,即使這是一個有點老貼出的問題;-)

5

我需要這個覆蓋默認的消息。通過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

0

嗯,這是有點愚蠢的,這是非常不可能的,任何人,但我會犯這樣的錯誤,但我已經把同一型號有兩種串行類,因此我有這個問題

希望我的錯誤幫助別人!

1

有同樣的問題,並從這個答案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')