自定义创建方法以防止重复

时间:2016-09-11 14:00:29

标签: python django django-rest-framework

我想在serializer.py中添加一些逻辑。

目前它会创建重复的标签(为该项目提供新的ID,但通常它会与标签名称匹配)。

用简单的英语

if exists:
   # Find the PK that matches the "name" field
   # "link" the key with Movie Class item
else:
   # Create the "name" inside of Tag class
   # "link" the key with Movie Class item

发布的数据如下所示:

{
  "title": "Test",
  "tag": [
    {
      "name": "a",
      "taglevel": 1
    }
  ],
  "info": [

  ]
}

Models.py

class Tag(models.Model):
    name = models.CharField("Name", max_length=5000, blank=True)
    taglevel = models.IntegerField("Tag level", blank=True)
    def __str__(self):
        return self.name

class Movie(models.Model):
    title = models.CharField("Whats happening?", max_length=100, blank=True)
    tag = models.ManyToManyField('Tag', blank=True)
    def __str__(self):
        return self.title

串行器

class MovieSerializer(serializers.ModelSerializer):
    tag = TagSerializer(many=True, read_only=False)
    class Meta:
        model = Movie
        fields = ('title', 'tag', 'info')

    def create(self, validated_data):
        tags_data = validated_data.pop('tag')
        movie = Movie.objects.create(**validated_data)
        for tag_data in tags_data:
            movie.tag.create(**tag_data)
        return movie

1 个答案:

答案 0 :(得分:1)

这可能会解决您的问题:

tag = Tag.objects.get_or_create(**tag_data)[0]
movie.tag.add(tag)

get_or_create函数返回元组(instance, created),因此您必须使用instance获取[0]

所以完整的代码是:

def create(self, validated_data):
    tags_data = validated_data.pop('tag')
    movie = Movie.objects.create(**validated_data)
    for tag_data in tags_data:
        tag = Tag.objects.get_or_create(**tag_data)[0]
        movie.tag.add(tag)
    return movie

要使功能不区分大小写,您必须手动“获取或创建”(主要部分是在__iexact中使用filter):

tag_qs = Tag.objects.filter(name__iexact=tag_data['name'])
if tag_qs.exists():
    tag = tag_qs.first()
else:
    tag = Tag.objects.create(**tag_data)
movie.tag.add(tag)