Django从post_保存信号访问许多字段

Django从post_保存信号访问许多字段,django,django-models,django-signals,Django,Django Models,Django Signals,我有一个Django模型,我想在保存时或保存后修改对象权限。我已经尝试了一些解决方案,并且post_save信号似乎是我想要做的事情的最佳候选者: class Project(models.Model): title = models.CharField(max_length=755, default='default') assigned_to = models.ManyToManyField( User, default=Non

我有一个Django模型,我想在保存时或保存后修改对象权限。我已经尝试了一些解决方案,并且
post_save
信号似乎是我想要做的事情的最佳候选者:

    class Project(models.Model):
        title = models.CharField(max_length=755, default='default')
        assigned_to = models.ManyToManyField(
            User, default=None, blank=True, null=True
        )
        created_by = models.ForeignKey(
            User,
            related_name="%(app_label)s_%(class)s_related"
        )


    @receiver(post_save, sender=Project)
    def assign_project_perms(sender, instance, **kwargs):
        print("instance title: "+str(instance.title))
        print("instance assigned_to: "+str(instance.assigned_to.all()))
在这种情况下,当创建项目时,信号触发,我看到
标题
,但
分配给
字段的列表为空


保存后,如何访问分配给数据的已保存的
文件?

您不打算这样做。m2m是在保存实例之后保存的,因此在所有m2m更新中不会有任何记录。进一步的问题(即使您解决了这个问题)是,您仍然处于事务中,查询数据库无论如何都无法获得具有正确状态的m2m

解决方案是挂接到
m2m\u changed
信号,而不是
post\u save

如果您的m2m可以为空(
blank=True
),那么您的发送者将被
Project.分配到。通过

),因为如果m2m未设置,则
m2m\u changed
不会触发,所以您的问题不大。您可以通过同时使用
post_save
m2m_changed
来解决此问题。但这种方法有一个很大的缺点——如果m2m字段不是空的,代码将执行两次

因此,您可以使用事务(Django 1.9+

Django提供了
on_commit()
函数来注册回调 事务成功后应执行的功能 承诺

重要提示:此方法仅在代码调用
save()
时有效。
post\u save
在仅调用
instance.m2m.add()
instance.m2m.set()
的情况下,信号根本不会触发

您应该使用
Concern
作为
sender
对象,或者将模型名称改为
Project
Concern
实际上是一个抽象基类。现在编辑。我对ForeignKey也有同样的问题,但显然没有信号?+1用于识别发送者(多对多_字段。到)。如果m2m关系没有用显式模型定义,那么它很方便。似乎在管理中没有触发
m2m_changed
。对吗?可能与此相关:我尝试过使用on_commit和post save(您编写的最后一个代码),但m2m模型中的更改仍然没有应用。@Daniel可能您的代码根本没有调用
save()
,这就是
post_save
信号不起作用的原因。
from django.db import transaction

def on_transaction_commit(func):
    def inner(*args, **kwargs):
        transaction.on_commit(lambda: func(*args, **kwargs))

    return inner

@receiver(post_save, sender=SomeModel)
@on_transaction_commit
def my_ultimate_func(sender, **kwargs):
    # Do things here