0

I have an Tag model, a News model and a Activity model. A news object can have many tags. Also an activity object can have many tags.

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)

Now I am creating a new activity object whenever a new news object is created using the django Signals.

@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()

The news object is created without any issues, it has all the filled in values (including the tags). The activity object is also created without any issues. However, the tags of the news object is NOT getting initialized into the activity object. Even the value of activity.verb is also None, which instead should have given me a tag name one of the news object's tag.

Even this doesn't work

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

What am I missing here? Your help will be very grateful. Thank you.

Aamu
  • 3,431
  • 7
  • 39
  • 61
  • I guess [here](http://stackoverflow.com/questions/23795811/django-accessing-manytomany-fields-from-post-save-signal) you'll find the explanation of your problem. – Sergei Zherevchuk Jun 24 '16 at 16:24
  • @SergeyZherevchuk That was it. I changed the signals accordingly. Thank you so much. – Aamu Jun 24 '16 at 17:48

1 Answers1

0

So with Sergey's very helpful comment, I was able to get the tags of the News object to the Activity object.

I changed the post_save signal to m2m_changed signal. And also changed if kwargs.get('created', False') to 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()

Maybe this will be helpful to another user like me.

Aamu
  • 3,431
  • 7
  • 39
  • 61