python - 使用多对多记录链接到创建时的现有记录
问题描述
我在两个模型(地点和标签)之间有多对多的关系。但是,标签表中似乎存在不必要的重复。
例如,当使用现有标签创建新地点时,它会创建一个具有相同名称的重复标签并将其链接,而不是链接现有标签。
我认为使模型上的名称字段唯一会有所帮助,但在运行发布请求时会导致以下错误,这是可以理解的:
{"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',)
解决方案
问题出在你的get_or_create
线路上。首先,您在现有place.tags.all()
QuerySet 上调用该方法,并且由于您正在创建一个新位置,这将永远不会返回现有对象。
其次,get_or_create(defaults=None, **kwargs)
有两组参数:
kwargs
:要搜索的值,您在其中包含place
冗余,因为您已经在place.tags
. 但本质上你是在说:找到我现有Tag
的具有相同tag_data
and的对象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)
推荐阅读
- web-services - 在 WCF 客户端中应该绑定什么以使用 OAuth 身份验证调用 SOAP Web 服务
- scala - Spark Scala:无法执行用户定义的函数原因:SparkException:必须在您的配置中设置主 URL
- python - YouTube-DL 的 Python GTK GUI 在窗口中显示进度
- jqgrid - jqgrid 自定义过滤器值应设置为现有工具栏
- c++ - 如何根据字符字母计算字符串中出现的次数?
- python - scipy.optimize.fmin_cg 函数需要两个可调用函数 f 和 fprime,如何从返回两个值的函数中提取两个函数?
- python - 如何在 JupyterLab 中压缩文件夹?
- python - 我做了一个函数,但得到一个“NoneType”对象不可调用
- fonts - 字体真棒图标出现损坏
- ubuntu-18.04 - 与远程主机的 scp 连接超时?