在Django中的save方法中动态添加多对多关系

在Django中的save方法中动态添加多对多关系,django,django-models,many-to-many,django-orm,Django,Django Models,Many To Many,Django Orm,我的内容模型与标记模型有多对多关系。保存内容对象时,我希望动态添加关系。我是这样做的 # 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.Mode

我的内容模型与标记模型有多对多关系。保存内容对象时,我希望动态添加关系。我是这样做的

# 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中运行以下命令,那么tags字段设置得非常完美

# python manage.py shell
from myapp.models import *
obj = Content.objects.get(pk=1)
tag_content(obj.pk)

那么,为什么shell版本可以工作,而另一个却不能?非常感谢您的帮助。

由于Django将m2m关系写入数据库的方式,您无法使用自定义
保存
方法处理m2m关系。使用m2m关系保存模型实例时,Django首先写入对象,然后再次进入并写入适当的m2m关系。因为m2m的东西是“第二个”,所以尝试在自定义保存中处理关系是失败的

解决方案是使用删除自定义保存内容并将其添加到模型定义下面,确保导入
receiver
post\u 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)
您的
tagg_content
函数可能应该将
is_taged
交换为
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关系时非常重要。

这不是问题的原因,但为什么不将内容项本身传递给标记内容,而不是pk?这样你就不必从数据库中重新查询它了。好的观点。我会这样做的。但正如你所说,这不是解决我问题的办法。好吧,我已经试过了。然而,我不断得到另一个错误:不可破坏的类型“list”。它引用add()函数。知道为什么会发生这种情况吗?尝试添加一组查询对象,而不是一组数字