2017-09-14 81 views
0

排除我有M2M相關實體:Django的REST框架序列化:從確認相關的實體

class Tag(models.Model): 
    name = models.CharField(
     max_length=80, 
     blank=False, 
     unique=True 
) 

class File(models.Model): 
    tags = models.ManyToManyField(Tag) 
    uploader = models.ForeignKey(User, on_delete=models.DO_NOTHING) 

    name = models.CharField(
     max_length=255, 
     blank=False, 
     unique=True, 
    ) 

和串行他們:

class TagSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Tag 
     fields = ('id', 'name') 
     extra_kwargs = { 
      'name': { 
       'validators': [], 
      }, 
     } 

class FileSerializer(serializers.ModelSerializer): 
    tags = TagSerializer(many=True, read_only=False) 

    class Meta: 
     model = File 
     fields = ('id', 'name', 'tags') 

    def update(self, instance, validated_data): 
     tags_data = validated_data.pop('tags') 

     if 'name' in validated_data: 
      instance.name = validated_data['name'] 


     instance_tags = instance.tags.all() 
     new_tag_list = [] 

     # add new tags 
     for tag in tags_data: 
      tag, created = Tag.objects.get_or_create(name=tag['name']) 
      new_tag_list.append(tag) 
      if tag not in instance_tags: 
       instance.tags.add(tag) 

     # remove old tags 
     for instance_tag in instance_tags: 
      if instance_tag not in new_tag_list: 
       instance.tags.remove(instance_tag) 

     return instance 

,你可以看到我關掉所有驗證的標籤。在TagSerializer中通過此代碼設置的名稱字段:extra_kwargs = {'name': {'validators': []}} 這是因爲在保存更新過程中驗證錯誤:

serializer = FileSerializer(file, data=request.data, partial=True) 
if serializer.is_valid(): 
    ... 

如果您的文件帶有標籤列表,並且只想添加或刪除一些標籤,則會出現錯誤'標籤已存在此類名稱'。

所以這個秒數正在工作,但現在我沒有對Tag.name的唯一檢查。 我試着寫東西像什麼FileSerializer:

class FileSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = File 
     extra_kwargs = { 
      'tags': { 
       'validators': [], 
      }, 
     } 

但當然不工作。 問題是關於任何可能性,當我添加/刪除與文件的綁定時,根本不驗證標記實體。

+0

請加滿錯誤堆棧 –

+0

沒有錯誤堆棧DRF自動執行它,並返回400錯誤與正文:{「標籤」:[{「Name」:「這個名字標籤已經存在。」] },{「name」:[「這個名稱的標籤已經存在。」]}]} - 在這種情況下,文件有3個標籤,我試圖刪除一個,所以發送兩個列表,應該由代碼離開 – user7001187

+0

顯示我沒有看到「TagSerializer」的驗證,請告訴你apiview。 –

回答

0

您可以嘗試,這種方式爲update,但如果此解決方案適合您,您還需要覆蓋create方法。

class FileSerializer(serializers.ModelSerializer): 
    tags = TagSerializer(many=True, read_only=True) 
    #          ^^^^^^ 

    class Meta: 
     model = File 
     fields = ('id', 'name', 'tags') 

    def update(self, instance, validated_data): 
     # Override tags_data = validated_data.pop('tags') 
     # this way 
     request = self.context['request'] 
     tags_data = request.data.get('tags', []) 

     # Next your current code 

在串行初始添加extra-context,當您使用get_serializer方法添加views from drf 上下文。

serializer = FileSerializer(file, data=request.data, partial=True, context={'request': request}) 
+0

中聲明爲unique = True ,但self.context默認爲空dict – user7001187

+0

,當您使用drf時,您創建了帶有drf視圖和上下文非空的api,我更新了答案,您可以嘗試 –

+0

現在它工作,太棒了!謝謝你!所以我不得不在update和create方法中使用request.data而不是validated_data? – user7001187