Python 使用Django';s m2m_已更改,以修改添加前保存的内容

Python 使用Django';s m2m_已更改,以修改添加前保存的内容,python,django,django-signals,django-orm,m2m,Python,Django,Django Signals,Django Orm,M2m,我不太熟悉Django的信号,需要一些帮助 在保存实例之前,如何修改pk_集?我是否必须向信号调用者返回某些内容(如kwargs)?或者我自己保存实例 作为一个简单的例子:我想确保保存所有视频时,包含pk=1的类别。如果m2m_已更改,我将如何做到这一点 class Video(models.Model): category = models.ManyToManyField('Category') def video_category_changed(sender, **kwargs)

我不太熟悉Django的信号,需要一些帮助

在保存实例之前,如何修改pk_集?我是否必须向信号调用者返回某些内容(如
kwargs
)?或者我自己保存
实例

作为一个简单的例子:我想确保保存所有视频时,包含
pk=1
的类别。如果
m2m_已更改
,我将如何做到这一点

class Video(models.Model):
    category = models.ManyToManyField('Category')

def video_category_changed(sender, **kwargs):
    action = kwargs.pop('action', None)
    pk_set = kwargs.pop('pk_set', None)
    instance = kwargs.pop('instance', None)

    if action == "pre_add":
        if 1 not in pk_set:
            pk_set.update( [ 1 ] )  # adding this to the set
            # do something else?
            # profit?

m2m_changed.connect( video_category_changed, sender=Video.category.through )

只需更新
pku集
就足够了。你不需要做任何额外的工作。保存视频实例后,它将有一个pk=1的类别

from django.db import models
from django.db.models.signals import m2m_changed
from django.dispatch import receiver

class Category(models.Model):
    pass

class Video(models.Model):
    category = models.ManyToManyField('Category')

@receiver(m2m_changed, sender=Video.category.through)
def video_category_changed(sender, **kwargs):
    action = kwargs.pop('action', None)
    pk_set = kwargs.pop('pk_set', None)    
    if action == "pre_add":
        if 1 not in pk_set:
            pk_set.update([1])
在上述方法中,只有在保存视频实例后才会保存类别。如果要将它们显式保存在
m2m_changed
实例中,也可以按如下操作

@receiver(m2m_changed, sender=Video.category.through)
def video_category_changed(sender, **kwargs):
    instance = kwargs.pop('instance', None)
    pk_set = kwargs.pop('pk_set', None)
    action = kwargs.pop('action', None)
    if action == "pre_add":
        if 1 not in pk_set:
            c = Category.objects.get(pk=1)
            instance.category.add(c)
            instance.save()

不需要在信号中返回值。您也不需要保存实例。只需添加要在响应所选事件时执行的代码。有趣的是,有时一些小事情会让你感到困惑——我在测试这个时没有
pk=1
category对象。。。所以,当它不起作用时,我认为我丢失了一些信号,因为这是我第一次使用这些。。。事实上,我只是在装傻,而且一开始就做对了。谢谢你用例子给出了非常清晰的答案。搞定了。