使用 Signal 创建另一个对象时实例字段没有值

No value of the instance's field when creating another object with Signal

我有一个标签模型、一个新闻模型和一个 Activity 模型。一个新闻对象可以有很多标签。 activity 对象也可以有很多标签。

class Tag(models.Model):
    name = models.CharField(max_length=20, unique=True)

class News(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=150)
    tags = models.ManyToManyField(Tag)
    activity = GenericRelation(Activity)

class Activity(models.Model):
    actor_type = models.ForeignKey(ContentType, related_name='actor_type_activities')
    actor_id = models.PositiveIntegerField()
    actor = GenericForeignKey('actor_type', 'actor_id')
    verb = models.CharField(max_length=10)
    target_type = models.ForeignKey(ContentType, related_name='target_type_activities')
    target_id = models.PositiveIntegerField()
    target = GenericForeignKey('target_type', 'target_id')
    tags = models.ManyToManyField(Tag)

现在,每当使用 Django Signals 创建新的新闻对象时,我都会创建一个新的 activity 对象。

@receiver(post_save, sender=News)
def create_activity(sender, **kwargs):
    if kwargs.get('created', False):
        actor_type = ContentType.objects.get_for_model(kwargs.get('instance').user)
        actor_id = kwargs.get('instance').user.id
        target_type = ContentType.objects.get_for_model(kwargs.get('instance'))
        target_id = kwargs.get('instance').id
        if target_type.name == 'news':
            verb = 'published an article'
        else:
            verb = '-verb-'
        activity, created = Activity.objects.get_or_create(
            actor_type=actor_type,
            actor_id=actor_id,
            verb=verb,
            target_type=target_type,
            target_id=target_id
        )
        tags = activity.target.tags.all()
        activity.tags.add(*tags)
        activity.verb = "%s" % (tags.first())
        activity.save()

新闻对象的创建没有任何问题,它具有所有填充值(包括标签)。 activity 对象的创建也没有任何问题。但是,新闻对象的标签并未初始化到 activity 对象中。甚至 activity.verb 的值也是 None,它应该给我新闻对象标签之一的标签名称。

连这个都不行

tags = kwargs.get('instance').tags.all()

我在这里错过了什么?非常感谢您的帮助。谢谢。

因此,在 Sergey 非常有用的评论下,我能够将新闻对象的标签获取到 Activity 对象。

我将 post_save 信号更改为 m2m_changed 信号。并且还将 if kwargs.get('created', False') 更改为 if action=='post_add'.

@receiver(m2m_changed, sender=News.tags.through)
def add_tags_to_activity(sender, action, instance, **kwargs):
    if action == 'post_add':
        actor_type = ContentType.objects.get_for_model(instance.user)
        actor_id = instance.user.id
        target_type = ContentType.objects.get_for_model(instance)
        target_id = instance.id
        pub_date = instance.pub_date
        if target_type.name == 'news':
            verb = 'published an article'
        else:
            verb = '-verb-'
        activity, created = Activity.objects.get_or_create(
            actor_type=actor_type,
            actor_id=actor_id,
            verb=verb,
            target_type=target_type,
            target_id=target_id,
            pub_date=pub_date
        )
        activity.tags.add(*tags)
        activity.save()

也许这对像我这样的其他用户有帮助。