我在两个模型(位置和标签)之间有很多关系。但是,标签表中似乎有不必要的重复。
例如,当使用退出标签创建新地点时,它会创建一个具有相同名称的重复标签并将其链接,而不是链接已经存在的标签。
我认为使名称字段在模型上唯一会有所帮助,但可以理解,在运行发布请求时会导致以下错误:
{"tags":[{"name":["tags with this name already exists."]},{"name":["tags with th
is name already exists."]}]}
序列化器
class PlaceTagSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Tags
fields = ('name',)
class PlaceSerializerPost(serializers.ModelSerializer):
tags = PlaceTagSerializer(many=True)
class Meta:
model = Place
fields = ('title', 'lat', 'lon', 'tags', 'featured_image_url', 'created_at')
def create(self, validated_data):
tags_data = validated_data['tags']
"""
Tags need to be deleted otherwise the place object will not save
as they need to be handled separately.
"""
del validated_data['tags']
place = Place.objects.create(**validated_data)
for tag_data in tags_data:
place.tags.get_or_create(place=place, **tag_data)
return place
模型
class Tags(models.Model):
name = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
class Place(models.Model):
title = models.CharField(max_length=800)
lat = models.DecimalField(max_digits=20, decimal_places=10)
lon = models.DecimalField(max_digits=20, decimal_places=10)
featured_image_url = models.CharField(max_length=2000)
created_at = models.DateTimeField(auto_now_add=True)
tags = models.ManyToManyField(Tags)
live = models.BooleanField(default=1)
def __str__(self):
return self.title
class Meta:
ordering = ('title',)
答案 0 :(得分:0)
问题出在您的get_or_create
行上。首先,您正在现有的place.tags.all()
QuerySet上调用该方法,并且由于要创建一个新位置,因此它将永远不会返回现有对象。
第二,get_or_create(defaults=None, **kwargs)
有两组参数:
kwargs
:要搜索的值,其中已经多余地包含了place
,因为您已经在place.tags
上进行了过滤。但实际上您是在说:找到具有相同的Tag
和tag_data
的现有place
对象。defaults
:将为新对象设置这些属性,但不会搜索。由于Tag
只有一个字段,因此此处无需设置任何内容。因此,您应该这样做:
tag, _ = Tag.objects.get_or_create(**tag_data)
# I'm not sure what `tag_data` is, but it should be dictionary {'name': 'some tag name'}, if not:
tag, _ = Tag.objects.get_or_create(name=tag_data)
place.tags.add(tag)