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.
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.