Reputation: 912
I am trying to add a Post to a list view, the Home list view has already an Item context.
In my project, a user can add a post and add an item each is a different app with different models.
So In my Home list view, I have my items looped and in each item, it is showing the user related to it.
What I am trying to do is check if this item.user has a post which is admin_approved=True
related to the user and if it does exist a button show appears in the page linking to another page with these posts.
So if there are Zero posts related to the user or posts available but admin_approved=False
or not yet admin_approved=True
the button should not appear but if there is 1 or more posts that are admin_approved=True
the button should appear.
I have tried to annotate the queryset but the issue is that when a user has 2 posts one which is approved and another not approved, 2 items appears one with the button and one without the button and duplication takes place in the homepage List view
I have tried to use .distinct() but it didn't work items are still duplicated
Here is the models.py
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, unique=True)
admin_approved = models.BooleanField(default=False)
here is the views
from .models import Item
from django.db.models import Case, When, BooleanField, Q
class HomeView(ListView):
model = Item
paginate_by = 12
template_name = "home.html"
ordering = ['-timestamp']
def get_queryset(self):
has_post = Case(
When(Q(designer__post__isnull=False) & Q(designer__post__admin_approved=True), then=True),
default=False,
output_field=BooleanField()
)
return super().get_queryset().annotate(has_post=has_post).distinct()
here is the template
{% for item in object_list %}
{{ item.title }}
{% if item.has_post %}
SHOW BUTTON
{% else %}
HIDE BUTTON
{% endif %}
{% endfor %}
here is the item model
class Item(models.Model):
designer = models.ForeignKey(
User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
Upvotes: 1
Views: 96
Reputation: 476614
It will repeat each Item
for each designer__post
combination, since you do not use a "fold" function.
You can make use of an Exists
subquery [Django-doc] instead:
from django.db.models import Exists, OuterRef
class HomeView(ListView):
model = Item
paginate_by = 12
template_name = "home.html"
ordering = ['-timestamp']
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).annotate(
has_post=Exists(
Post.objects.filter(
designer_id=OuterRef('designer_id'),
admin_approved=True
)
)
)
Upvotes: 1