我的内容模型与Tag模型有多对多的关系。当我保存Content对象时,我想动态添加关系。我这样做的方式如下。
# models.py
def tag_content(content_id):
obj = Content.objects.get(pk=content_id)
print obj # Checking
obj.tags = [1, 2, 3] # Adding the relationships using the Tag IDs
class Tag(models.Model):
name = models.CharField(max_length=255)
class Content(models.Model):
title = models.CharField(max_length=255)
is_tagged = models.BooleanField(default=False)
tags = models.ManyToManyField(Tag, blank=True)
def save(self, *args, **kwargs):
super(Content, self).save(*args, **kwargs)
if not self.is_tagged:
tag_content(self.pk) # calling the tagging method
换句话说,当保存Content对象时,其tags对象与3个不同的Tag对象模型相关。只是为了让你知道,我确实在数据库中有pks = 1,2和3的标签。
但是,这根本不起作用。 save方法调用tag_content方法,因为print obj语句有效。但是,多对多字段未设置并保持为空。有趣的是,如果我在shell中运行以下命令,则标记字段设置完美。
# python manage.py shell
from myapp.models import *
obj = Content.objects.get(pk=1)
tag_content(obj.pk)
那么shell版本是如何工作的,但是另一个版本没有?任何帮助表示赞赏。
答案 0 :(得分:3)
由于Django将这些关系写入数据库的方式,您无法在自定义save
方法中处理m2m关系。当保存具有m2m关系的模型实例时,Django首先写入对象然后再次进入并写入适当的m2m关系。由于m2m的东西是“第二”,试图在自定义保存中处理关系失败。
解决方案是使用post-save signal.删除自定义保存内容并将其添加到模型定义下方,确保导入receiver
和post_save
:
@receiver(post_save, sender = Content)
def update_m2m_relationships_on_save(sender, **kwargs):
if not kwargs['instance'].is_tagged:
tag_content(kwargs['instance'].pk)
您的tag_content
函数可能应该将is_tagged
交换为True
,然后保存实例;如果那个布尔值永远不会翻转那么这可能只是在无限循环中运行。您也可以传入对象而不是传入pk:
def tag_content(thing_to_tag):
thing_to_tag.tags.add([1,2,3])
thing_to_tag.is_tagged = True
thing_to_tag.save()
return thing_to_tag
请注意.add()
的使用,这在添加m2m关系时非常重要。