如何将一个对象的字段复制到另一个对象的字段

How to copy an object's field to another object's field

我有一个 activity 模型,它会在创建新闻对象时创建一个 activity 对象。 News 对象有它的标签。

class Tag(models.Model):
    slug = models.SlugField()

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()
    ...
    ...
    target_type = models.ForeignKey(ContentType, related_name='target_type_activities')
    target_id = models.PositiveIntegerField()
    target = GenericForeignKey('target_type', 'target_id')
    tags = models.ManyToManyField(Tag)

现在使用信号,我尝试以这种方式获取新闻对象的标签,

@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
        ...
        ...
        # this didn't work
        tags = kwargs.get('instance').tags.all()
        # even this didn't work
        tags = target_type.get_object_for_this_type(id=target_id).tags.all()

        activity = Activity.objects.get_or_create(
            actor_type=actor_type,
            actor_id=actor_id,
            verb=verb,
            target_type=target_type,
            target_id=target_id,
            tags=tags,
            pub_date=pub_date
        )

但是我得到一个错误:

'tags' is an invalid keyword argument for this function

如何将新闻对象的标签复制到 Activity 对象的标签列表?

我认为将 kwargs.get('instance') 存储在变量中然后使用它会更简洁。这也将消除您的错误。然后必须在创建 activity 对象后分配标签。

if kwargs.get('created', False):
    news_obj = kwargs.get('instance')
    if not news_obj:
        return
    actor_type = ContentType.objects.get_for_model(news_obj.user)
    actor_id = news_obj.user.id
    target_type = ContentType.objects.get_for_model(news_obj)
    target_id = news_obj.id
    ...
    ...
    tags = news_obj.tags.all()

    activity = 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()

你应该注意你得到的回溯。即使您没有在此处发布它,也可以清楚地看到错误是在您创建 Activity 时出现的,而不是在您从新闻中读取标签时出现的。那是因为在实例化模型时无法为多对多字段传入数据 - 因为需要先保存对象,然后才能为其分配 M2M 关系。

您应该从 get_or_create 调用中取出 tags 行,然后再分配它们。