2017-05-23 51 views
0

寫入ForeignKey相關項目已存在的嵌套序列化程序的最佳方法是什麼?在Django Rest Framework中編寫一個嵌套的序列化程序並觸發驗證程序問題

示例 - 我有一對多的Survey模型和SurveyReponse模型。尚未創建Survey模型的新SurveyResponse模型的POST沒有問題,以及未定義特定Survey模型且默認爲特定Survey模型的模型的POST。然而,試圖提供該領域似乎會導致類似於過去問過的這個問題的驗證器問題:https://github.com/encode/django-rest-framework/issues/2996 似乎不像添加驗證器= []修復了我的問題。

我到目前爲止所做的: 我設置了我的SurveyReponse.create()方法,可以發佈SurveyResponse提供NO調查,並將其保存到默認Survey中。 這很好。 即,

{ "rating": 10 } 

一個POST創建一個新的SurveyReponse對象,還將其與名涉及調查:「默認調查名稱」

我想要做什麼其他: 我希望能夠POST提供一個特定的調查來與我的SurveyReponse關聯。

{ 
"rating": 10, 
"survey": {"name": "Other Survey Name"} 
} 

如果調查還不存在,但是,如果調查已經存在這正常工作與我當前的代碼,我打的唯一標識符重複錯誤

{ 
    "survey": { 
    "name": [ 
     "survey with this name already exists." 
    ] 
    } 
} 

如何得到解決這個? 通過刪除這一行,

 survey = SurveySerializer(required=False) 

我能夠做我想做的,但我只是提供鏈接到資源,當我想能夠只需要提供名字。 (除非這整個想法是一個反模式什麼的,在這種情況下,我應該永遠都只是被寫入/調查/對象,而不是)

抽樣調查和調查回覆:

高級模式:

class Survey(models.Model): 
    created = models.DateTimeField(auto_now_add=True) 
    name = models.CharField(max_length=255, unique=True) 
    creator = models.ForeignKey(
     'auth.User', 
     related_name='survey', 
     to_field='id', 
     null=True, 
    ) 

class SurveyResponse(models.Model): 
    """Response to the Survey""" 
    survey = models.ForeignKey(Survey, blank=True) 
    created = models.DateTimeField(auto_now_add=True) 
    rating = models.IntegerField(blank=False) 
    creator = models.ForeignKey(
     'auth.User', 
     related_name='survey_response', 
     to_field='id', 
     null=True, 
    ) 

串行器

class SurveySerializer(serializers.HyperlinkedModelSerializer): 
    creator = serializers.ReadOnlyField(source='creator.username') 
    class Meta: 
     model = Survey 
     fields = '__all__' 

class SurveyResponseSerializer(serializers.HyperlinkedModelSerializer): 
    '''Question Serializer''' 
    creator = serializers.ReadOnlyField(source='creator.username') 
    survey = SurveySerializer(required=False) 
    def create(self, validated_data): 
     default_survey_name = "Default Survey Name" 
     survey_data = validated_data.pop('survey', None) 
     if survey_data is None: 
      try: 
       survey = Survey.objects.get(name=default_survey_name) 
       validated_data['survey'] = survey 
      except: 
       print("Unable to get Survey, creating a new one") 
       survey = Survey.objects.create(
        name=default_survey_name, 
        description=default_survey_name, 
        creator=self.context['request'].user 
       ) 
       validated_data['survey'] = survey 
     else: 
      survey, survey_created = Survey.objects.get_or_create(**survey_data) 

     validated_data['survey'] = survey 
     instance = self.Meta.model(**validated_data) 
     instance.save() 
     return instance 

回答

0

我終於實現了這一系列的變化,以串行的去除驗證和CR期間手動執行的名稱驗證吃掉和更新。讓我知道是否有更習慣的方法!

class SurveySerializer(serializers.HyperlinkedModelSerializer): 
    creator = serializers.ReadOnlyField(source='creator.username') 

    def create(self, validated_data): 
     if Survey.objects.filter(name=self.validated_data['name']).exists(): 
      raise serializers.ValidationError("A survey with this name already exists") 
     return Survey.objects.create(**validated_data) 

    def update(self, instance, validated_data): 
     all_other_survey = Survey.objects.exclude(name=instance.name) 
     if all_other_survey.filter(name=self.validated_data['name']).exists(): 
      raise serializers.ValidationError("A survey with this name already exists (Not counting this instance)") 
     else: 
      instance.name = self.validated_data['name'] or instance.name 
     instance.save() 
     return instance 

    class Meta: 
     model = Survey 
     fields = '__all__' 
     extra_kwargs = { 
      'name': { 
       'validators': [], 
      } 
     } 
+0

發生錯誤時會發生什麼情況?你還是最終創建或重新使用調查?提高應該停止所有進一步的執行,但extra_kwargs沒有驗證器是什麼讓我不確定 – pravin

相關問題