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()))
この場合、プロジェクトが作成されると信号が発生し、title
が表示されますが、assigned_to
フィールドには空のリストが表示されます。
保存後に保存したassigned_to
データにアクセスするにはどうすればよいですか?
あなたは行くつもりはありません。 M2Mはインスタンスの保存後に保存されるため、すべてのm2m更新でレコードはありません。さらなる問題(それを解決したとしても)は、まだトランザクション内にあり、DBにクエリを実行しても、適切な状態のm2mが取得されないことです。
解決策は、m2m_changed
ではなくpost_save
信号にフックすることです。
https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed
送信者はProject.assigned_to.through
になります
M2mが空の場合(blank=True
)、m [m]が設定されていないとm2m_changed
が起動しないため、m2m_changed
で少し問題があります。この問題を解決するには、post_save
とm2m_changed
を同時に使用します。ただし、この方法には大きな欠点が1つあります。m2mフィールドが空でない場合、コードが2回実行されます。
したがって、トランザクションの on_commit (only Django> = 1.9)を使用できます
Djangoは、トランザクションが正常にコミットされた後に実行する必要があるコールバック関数を登録するon_commit()関数を提供しています。
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_untimate_func(sender, **kwargs):
# Do things here