Filter a contenttype with the content object's field

554 views
Skip to first unread message

Robin Lery

unread,
Jan 3, 2017, 2:13:58 PM1/3/17
to django...@googlegroups.com
I creating an app where users can post with its related tags:

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

class Post(models.Model):
    user = models.ForeignKey(User)
    body = models.TextField()
    tags = models.ManyToManyField(Tag)
    pub_date = models.DateTimeField(default=timezone.now)
    activity = GenericRelation(Activity)

class Activity(models.Model):
    actor = models.ForeignKey(User)
    verb = models.PositiveIntegerField(choices=VERB_TYPE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    pub_date = models.DateTimeField(default=timezone.now)

What I want to do is filter the Activity with the a list of users, and a list of tags of the from list of Post objects.

Eg:

UserA created a new Post obect with tags(#class, #school)
UserB created a new Post object with tags(#professor, #teacher)
UserC created a new Post object with tags(#school, #university)
UserD created a new Post object with tags(#university, #school)


So say I want to filter Activity with user_list=[UserA, UserC] and tag_list = [#class, #teacher]

It should return:

UserA created a new Post obect with tags(#class, #school)
UserC created a new Post object with tags(#school, #university)
UserB created a new Post object with tags(#professor, #teacher)

To filter the Activity with users, I can query this way:
Activity.objects.filter(actor__in=user_list)

But, how do I filter Activity with the content_object's (i.e.Post) field (i.e. Post.tags)? Is this even possible? I cannot figure it out. And your help will be very much helpful. Thank you.

Robin Lery

unread,
Jan 3, 2017, 2:32:46 PM1/3/17
to django...@googlegroups.com
I forgot to mention, there is another class:


class Photo(models.Model):
    user = models.ForeignKey(User)
    file = models.ImageField()

    tags = models.ManyToManyField(Tag)
    pub_date = models.DateTimeField(default=timezone.now)
    activity = GenericRelation(Activity)

So, filtering would be with the list of content_object's (i.e. Post of Photo) field (i.e. Post.tags or Photo.tags).

Michel Rodrigues

unread,
Jan 4, 2017, 7:46:47 AM1/4/17
to Django users
You may try add a related_query_name in the field activity:

activity = GenericRelation(Activity, related_query_name="post_tags")

https://docs.djangoproject.com/en/1.10/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation.related_query_name

I make a test: 'michel' has a Post1 with tag1, tag2, tag3 and Post2 with tag1 and tag2. 'ana' has a Post3 just with tag3

>>> Activity.objects.filter(post_tags__tags__name='tag1')
<QuerySet [<Activity: michel>, <Activity: michel>]>

>>> Activity.objects.filter(post_tags__tags__name='tag2')
<QuerySet [<Activity: michel>, <Activity: michel>]>

>>> Activity.objects.filter(post_tags__tags__name='tag3')
<QuerySet [<Activity: michel>, <Activity: ana>]>


PS: sorry for my English, it's not my native language
Message has been deleted

Michel Rodrigues

unread,
Jan 4, 2017, 7:58:38 AM1/4/17
to Django users
Sorry, the point is a list of tags as argument, you can do this:

>>> Activity.objects.filter(tags_act__tags__name__in=['tag1','tag3']).distinct()
<QuerySet [<Activity: michel>, <Activity: michel>, <Activity: ana>]>


Without .distinct() django return duplicated objects:

>>> Activity.objects.filter(tags_act__tags__name__in=['tag1','tag3'])
<QuerySet [<Activity: michel>, <Activity: michel>, <Activity: michel>, <Activity: ana>]>

Robin Lery

unread,
Jan 4, 2017, 4:03:09 PM1/4/17
to django...@googlegroups.com
Yes, this works. Thank you. But, as there are or will be more than one ContentType objects (i.e., Post model and Photo model), how do I iterate over it? Should I query them separately? Like
post_activities = Activity.objects.filter(post__tags__in=tags).distinct()
photos_activities = Activity.objects.filter(photo__tags__in=tags).distinct()

Or is there any better solution?

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/62094107-f03e-40ea-874f-d99f7a6dbcc7%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages