django queryset with count filter - django

I've done the entire Django Tutorial, but I couldn't figure out how to make the website display only Polls with Choices count bigger than 0.
I know that Poll.objects.get(pk=1).choice_set.count() would return the number of choices I have.
So I tried the filter Poll.objects.filter(choice_set.count()>0) and it didn't work.
Can someone help me please? Thanks
This is my actual queryset.
queryset=Poll.objects.filter(pub_date__lte=timezone.now).order_by('-pub_date')[:5]

queryset=Poll.objects.annotate(count=Count('choice')).filter(
pub_date__lte=timezone.now, count__gt=0).order_by('-pub_date')[:5]

Related

How to return just the id number from queryset for a counter?

I'm really just a beginner in python and django...
I'm looking for a way on how to get just the id of the last item in the queryset as a counter of posts for my project. I know about the ModelName.objects.last or .latest() however if I use last i still get the "Topic object (id)" I need just the id without the preceding text. Could anyone help me?

Django: How to create a field with many booleanfields?

I am trying to create a days_of_week model for my alarm app where users can just select the days of the week they want the alarm to go off. I want to use checkboxInput widget for it, but I can't find a way to find a field like that. Can someone show me how to make a field like that?
You can use CommaSeparatedIntegerField. More info in https://docs.djangoproject.com/en/dev/ref/models/fields/
You need to use a checkboxselectmultiple:
https://docs.djangoproject.com/en/dev/ref/forms/widgets/#checkboxselectmultiple
short example:
select = forms.MultipleChoiceField(choices=CHOICES, widget=forms.CheckboxSelectMultiple)
where CHOICES would be your days of the week.

Django multiple annotations with filter

Can anyone help me with this
qs = Vine.objects.annotate(votos_count=Count('votomoderacion')).\
annotate(votos_ok=Count('votomoderacion')).filter(votomoderacion__voto="1").\
annotate(votos_no_ok=Count('votomoderacion')).filter(votomoderacion__voto="0")
The problem is that the filters affects to all the annotations, and i want to filter every single annotation separately.
I hope i've been clair enough with my question.
Thank you!
You have to understand that what you are doing is chaining filters.
First you had a queryset with annotated votes count likeannotate(votos_ok=Count('votomoderacion')).filter(votomoderacion__voto="1").
Then you annotated votes_ok with it and filterered it like annotate(votos_ok=Count('votomoderacion')).filter(votomoderacion__voto="1"), which gave you another filtered queryset.
But after that, you added another filter annotate(votos_no_ok=Count('votomoderacion')).filter(votomoderacion__voto="0"), which filtered the queryset which you got from previous filter. so, in this case, you didn't get your desired result.
So better if you separate them. Like:
total_votes= Vine.objects.annotate(votos_count=Count('votomoderacion'))
yes_votes= Vine.objects.annotate(votos_ok=Count('votomoderacion')).filter(votomoderacion__voto="1")
no_votes= Vine.objects.annotate(votos_no_ok=Count('votomoderacion')).filter(votomoderacion__voto="0")
To join those queryset:
from itertools import chain
allvotes = list(chain(total_votes, yes_votes, no_votes))

Get most commented posts in django with django comments

I'm trying to get the ten most commented posts in my django app, but I'm unable to do it because I can't think a proper way.
I'm currently using the django comments framework, and I've seen a possibility of doing this with aggregate or annotate , but I can figure out how.
The thing would be:
Get all the posts
Calculate the number of comments per post (I have a comment_count method for that)
Order the posts from most commented to less
Get the first 10 (for example)
Is there any "simple" or "pythonic" way to do this? I'm a bit lost since the comments framework is only accesible via template tags, and not directly from the code (unless you want to modify it)
Any help is appreciated
You're right that you need to use the annotation and aggregation features. What you need to do is group by and get a count of the object_pk of the Comment model:
from django.contrib.comments.models import Comment
from django.db.models import Count
o_list = Comment.objects.values('object_pk').annotate(ocount=Count('object_pk'))
This will assign something like the following to o_list:
[{'object_pk': '123', 'ocount': 56},
{'object_pk': '321', 'ocount': 47},
...etc...]
You could then sort the list and slice the top 10:
top_ten_objects = sorted(o_list, key=lambda k: k['ocount'])[:10]
You can then use the values in object_pk to retrieve the objects that the comments are attached to.
Annotate is going to be the preferred way, partially because it will reduce db queries and it's basically a one-liner. While your theoretical loop would work, I bet your comment_count method relies on querying comments for a given post, which would be 1 query per post that you loop over- nasty!
posts_by_score = Comment.objects.filter(is_public=True).values('object_pk').annotate(
score=Count('id')).order_by('-score')
post_ids = [int(obj['object_pk']) for obj in posts_by_score]
top_posts = Post.objects.in_bulk(post_ids)
This code is shameless adapted from Django-Blog-Zinnia (no affiliation)

Get daily counts of objects from Django

I have a Django model with a created timestamp and I'd like to get the counts of objects created on each day. I was hoping to use the aggregation functionality in Django but I can't figure out how to solve my problem with it. Assuming that doesn't work I can always fall back to just getting all of the dates with values_list but I'd prefer to give the work to Django or the DB. How would you do it?
Alex pointed to the right answer in the comment:
Count number of records by date in Django
Credit goes to ara818
Guidoism.objects.extra({'created':"date(created)"}).values('created').annotate(created_count=Count('id'))
from django.db.models import Count
Guidoism.objects \
# get specific dates (not hours for example) and store in "created"
.extra({'created':"date(created)"})
# get a values list of only "created" defined earlier
.values('created')
# annotate each day by Count of Guidoism objects
.annotate(created_count=Count('id'))
I learn new tricks every day reading stack.. awesome!
Use the count method:
YourModel.objects.filter(published_on=datetime.date(2011, 4, 1)).count()