Reputation: 1962
I have user model with below fields..
class User(models.Model):
user_id = models.CharField(max_length=40,unique=True)
user_name = models.CharField(max_length=40)
user_email = models.EmailField()
user_city = models.CharField(max_length=40)
class Meta:
ordering = ['user_id']
verbose_name = 'User MetaData'
verbose_name_plural = 'Users MetaData'
def __unicode__(self):
return self.user_id
Now i want to filter top 10 cities by user i.e list of top 10 cities with number of users in that city. I used below syntax but always i am getting city_count = 1..
User.objects.annotate(city_count=models.Count('user_city')) .order_by('-city_count'))[:10]
i also tried below syntax but same result...
User.objects.values('user_city').annotate(city_count=models.Count('user_id')) .order_by('-city_count'))[:10]
Where i am doing wrong??
Upvotes: 1
Views: 60
Reputation: 2302
Your second example is right, just fix typos. Replace
User.objects.values('user_city').annotate(city_count=models.Count('user_id')) .order_by('-city_count'))[:10]
with
User.objects.values('user_city').annotate(city_count=models.Count('user_city')).order_by('-city_count')[:10]
UPDATE 1, 2:
top_cities_queryset = (User.objects
.values('user_city')
.annotate(user_city_count=models.Count('user_city'))
.order_by('-user_city_count')
.values_list('user_city', 'user_city_count'))
top_cities = [{city: count} for city, count in top_cities_queryset]
Upvotes: 1
Reputation: 13731
I don't think you can do this without a a model that has a relationship to User
. Basically you'd need to run the query on another model, then annotate the user_city from that other model. It's a bit weird for your specific case.
However, you can do this in Python. Here's how I'd do it:
from collections import Counter
city_counter = Counter(User.objects.values_list('user_city', flat=True))
top_ten_cities_and_counts = city_counter.most_common()[:10]
top_ten_cities = [city for city, count in top_ten_cities_and_counts]
Upvotes: 2