在Django的保存方法中动态添加多对多关系
我的内容模型与标记模型具有多对多关系。当我保存一个Content对象时,我想动态地添加这些关系。我以下面的方式做这件事。在Django的保存方法中动态添加多对多关系
# 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
换句话说,当内容物被保存,它的标签字段与3个不同的标签对象模型。只是为了让你知道,我确实在数据库中有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的版本是如何工作的,但另一个没有?任何帮助表示赞赏。
由于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的关系时,这是非常重要的。
好的,我试过了。但是,我不断收到另一个错误:不可用类型'列表'。它引用了add()函数。任何想法为什么发生这种情况? –
尝试添加一组查询对象而不是数字列表 – souldeux
不是你问题的原因,但你为什么不将内容项本身传递给tag_content而不是pk?然后你不必从数据库中重新查询它。 –
好点。会做到这一点。但正如你所说,不是解决我的问题。 –