Django 管理员保存不发送带有 m2m_changed 信号的 post_remove 操作

发布于 2024-11-08 17:29:40 字数 2089 浏览 5 评论 0原文

当我保存相关模型时,我试图获取多对多模型进行更新。使用 m2m_changed 信号 应该可以实现这一点(并且它可以工作!但不能在管理员?)例如,

# i want the references field to update when related model is saved.
# so just call count_references

class Tag(models.Model):
    """Group everything into categories"""
    # stuff stuff stuff
    references = models.IntegerField(default=0, editable=False)

    def count_references(self):
        # just add up references each time to save headaches
        self.references = 0
        # search for reverse managers
        sets = re.compile('^\w+_set$')
        for rel_set in [method for method in dir(self) if sets.match(method)]:
            self.references += getattr(self, rel_set).count()
        self.save()

class Entry(models.Model):
    """Blog entry"""
    # stuff stuff stuff
    tags = models.ManyToManyField('Tag', blank=True)

# this will call count_references when entry adds or removes tags

@receiver(m2m_changed, sender=Entry.tags.through)
def update_tag_ref_count(sender, instance, action, reverse, model, pk_set, **kwargs):
    print action
    if not reverse and action == 'post_add' or action == 'post_remove':
        for tag_pk in pk_set:
            print tag_pk
            Tag.objects.get(pk=tag_pk).count_references()
            print Tag.objects.get(pk=tag_pk).references

在 shell 中运行时,一切都运行良好。例如,使用像这样的tests.py:

t = Tag.objects.all()[0]
s = Snippet.objects.all()[0]

s.tags.remove(t)
s.save()

s.tags.add(t)
s.save()

我得到以下内容(其中“test”是正在打印的标签名称):

pre_remove
post_remove
test
0
pre_add
post_add
test
1

完美!当我向管理中的条目添加标签时,我得到以下信息(在 HTTP 内容之间):

pre_clear
post_clear
pre_add
post_add
test
1

仍然很好!不确定需要什么 pre/post_clear...当我删除时:

pre_clear
post_clear

啊! pre/post_remove 没有被调用! pre/post_clear 是无用的,并且它不提供任何主键。这感觉像是管理实施中的一个错误。有什么建议吗?

更新Bug #16073 提交并接受。

I'm trying to get a many to many model to update when I save a related model. This should be possible using the m2m_changed signal (and it works! but not in the admin?) e.g.

# i want the references field to update when related model is saved.
# so just call count_references

class Tag(models.Model):
    """Group everything into categories"""
    # stuff stuff stuff
    references = models.IntegerField(default=0, editable=False)

    def count_references(self):
        # just add up references each time to save headaches
        self.references = 0
        # search for reverse managers
        sets = re.compile('^\w+_set

Everything works perfectly when run in the shell. e.g. with a tests.py like so:

t = Tag.objects.all()[0]
s = Snippet.objects.all()[0]

s.tags.remove(t)
s.save()

s.tags.add(t)
s.save()

I get the following (where 'test' is the tag name being printed):

pre_remove
post_remove
test
0
pre_add
post_add
test
1

perfect! And when I add a tag to an entry in the admin I get the following (between HTTP stuff):

pre_clear
post_clear
pre_add
post_add
test
1

still good! not sure what pre/post_clear was called for... and when I remove:

pre_clear
post_clear

argh! pre/post_remove is not called! pre/post_clear is useless as well as it doesn't provide any primary keys. this feels like a bug in the admin implementation. any suggestions?

Update: Bug #16073 filed and accepted.

) for rel_set in [method for method in dir(self) if sets.match(method)]: self.references += getattr(self, rel_set).count() self.save() class Entry(models.Model): """Blog entry""" # stuff stuff stuff tags = models.ManyToManyField('Tag', blank=True) # this will call count_references when entry adds or removes tags @receiver(m2m_changed, sender=Entry.tags.through) def update_tag_ref_count(sender, instance, action, reverse, model, pk_set, **kwargs): print action if not reverse and action == 'post_add' or action == 'post_remove': for tag_pk in pk_set: print tag_pk Tag.objects.get(pk=tag_pk).count_references() print Tag.objects.get(pk=tag_pk).references

Everything works perfectly when run in the shell. e.g. with a tests.py like so:

I get the following (where 'test' is the tag name being printed):

perfect! And when I add a tag to an entry in the admin I get the following (between HTTP stuff):

still good! not sure what pre/post_clear was called for... and when I remove:

argh! pre/post_remove is not called! pre/post_clear is useless as well as it doesn't provide any primary keys. this feels like a bug in the admin implementation. any suggestions?

Update: Bug #16073 filed and accepted.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

油焖大侠 2024-11-15 17:29:40

(将其创建为社区 wiki,以将其作为“未回答”的问题来结束。)

这是 Django 中的一个错误。 OP 在 https://code.djangoproject.com/ticket/16073 提交了一张票证。

(Creating this as a community wiki to close out this as an "unanswered" question.)

This is a bug in Django. OP filed a ticket at https://code.djangoproject.com/ticket/16073.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文