【问题标题】:Django Add list generated from the text of one field to many to many fieldDjango将从一个字段的文本生成的列表添加到多对多字段
【发布时间】:2017-04-19 18:40:32
【问题描述】:

尝试将项目列表批量添加到多对多字段时遇到了一些麻烦,尽管尝试了各种方法,但不知道如何解决这个问题。我查看了 Django 文档,但似乎找不到我要找的东西。

这是我的模型的代码:

class Subject(models.Model):
    noun = models.CharField(max_length=30, null=True, blank=True)

class Knowledge(models.Model):
    item_text = models.TextField()
    item_subjects =  models.ManyToManyField(Subject, null=True, blank=True)

def add_subjects(sender, instance, *args, **kwargs):

    if instance.item_info:
         item_subjects = classifier.predict_subjects(instance.item_info)

         if item_subjects:
             ....

post_save.connect(add_subjects, sender=Knowledge)

列表由classifer.predict_subjects 函数生成。 我尝试使用m2m_changed 连接器和pre_savepost_save 连接。我什至不确定多对多字段是否是正确的选择,建立外键关系会更好。 代替'...' 我已经尝试过了,但它不会创建之间的关系,只会保存最后一个。

for sub in item_subjects:
    subject = Subject(id=instance.id, noun=sub)
    subject.save()

我也试过

instance.item_subjects = item_subjects

还有很多我不记得的事情,老实说,我真的不认为我在正确的范围内。有什么建议吗?

编辑:

好的,所以我已经添加了所有列表项,但仍然没有设法将这些项目链接到多对多字段。

        for sub in item_subjects:
            subject = Subject.objects.get_or_create(noun=sub)

编辑 2:

因此,在 Django shell 的循环之外执行几乎完全相同的操作似乎可以正常工作并保存条目,但它不在函数内部。

>>> k[0].item_subjects.all()
<QuerySet []>
>>> d, b = Subject.objects.get_or_create(noun="cats")
<Subject: cats>
>>> k[0].item_subjects.add(d)
>>> k[0].item_subjects.all()
<QuerySet [<Subject: cats>]>

编辑 3

所以我接受了 Robert 的建议,它就像上面一样在 shell 中工作,只是在管理界面中使用它时不行。我的代码中的打印语句显示正在更新的数组项,但它只是不会持续存在。我四处阅读,这似乎与管理表单在保存之前清除项目有关。

def sub_related_changed(sender, instance, *args, **kwargs):

    print instance.item_subjects.all()

    if instance.item_info:
        item_subjects = classifier.predict_subjects(instance.item_info)

        if item_subjects:
            for sub in item_subjects:
                subject, created = Subject.objects.get_or_create(noun=sub)
                instance.item_subjects.add(subject)

        print instance.item_subjects.all()


post_save.connect(sub_related_changed, sender=Knowledge)

我已经尝试使用函数作为 m2m_changed 信号如下:

m2m_changed.connect(model_saved, sender=Knowledge.item_subjects.through)

但这要么生成递归循环,要么不会触发。

【问题讨论】:

    标签: python django django-models django-orm


    【解决方案1】:

    一旦您拥有 subject 对象(就像您在编辑中所做的那样),您可以使用

    添加它们
    for sub in item_subjects:
        subject, created = Subject.objects.get_or_create(noun=sub)
        instance.item_subjects.add(subject)
    

    “item_subjects”属性是一种管理相关项目的方式。直通关系是通过“add”方法创建的。

    完成此操作后,您可以执行instance.item_subjects.filter(noun='foo')instance.item_subjects.all().delete() 等操作

    文档参考:https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_many/

    编辑 啊,我没有意识到这是在 Django Admin 中发生的。我认为你是对的,这就是问题所在。保存时,管理员调用两个方法:第一个是 model_save(),它调用模型的 save() 方法(我假设这段代码存在)。它调用的第二个方法是“save_related”,它首先清除多对多关系,然后根据提交的表单数据保存它们。在您的情况下,没有有效的表单数据,因为您在保存时创建了对象。

    如果您将此代码的相关部分放入管理员的 save_related() 方法中,则更改应该会持续存在。

    如果您同时发布 /models.py 和 /admin.py 文件,我可以更具体地说明它应该放在哪里。

    来自另一个 SO 问题的参考: Issue with ManyToMany Relationships not updating inmediatly after save

    【讨论】:

    • 感谢您的帮助,由于某种原因它仍然无法正常工作。不过,在 django shell 中尝试几乎相同的东西是可行的。例如&gt;&gt;&gt; k[0].item_subjects.all() &lt;QuerySet []&gt; &gt;&gt;&gt; d, b = Subject.objects.get_or_create(noun="cats") &gt;&gt;&gt; d &lt;Subject: cats&gt; &gt;&gt;&gt; k[0].item_subjects.add(d) &gt;&gt;&gt; k[0].item_subjects.all() &lt;QuerySet [&lt;Subject: cats&gt;]&gt; 我还有其他事情要做吗。
    • 很高兴它在 shell 中工作。现在您已经添加了 .add() 方法,介意编辑以显示您在 shell 外部使用的新代码(仍然无法工作的代码?)?
    • 啊,我没有意识到这是在管理员中发生的。我认为您对管理员覆盖问题可能是正确的。刚刚对我的答案进行了另一次更新。
    猜你喜欢
    • 1970-01-01
    • 2012-04-27
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    相关资源
    最近更新 更多