I have a profile model with a ManyToMany
field called that relates to a Stock
. In my admin dashboard I'm trying to show the number of watchlists each stock is in. The annotation query I have is:
qs.annotate(watchlist_count=Count('profile__watchlist__symbol'))
But it's returning incorrect results
Here are the models:
class Profile(models.Model):
user = OneToOneField(User, on_delete=models.CASCADE)
watchlist = ManyToManyField(Stock, blank=True)
def __str__(self):
return self.user.email
class Stock(models.Model):
symbol = CharField(max_length=15, unique=True)
name = CharField(max_length=100)
category = CharField(max_length=30, choices=CATEGORY_CHOICES, blank=True)
about = TextField(help_text='About this company')
def __str__(self):
return f'{self.symbol} - {self.name}'
The equivalent SQL query is:
select stock_id, count(stock_id) from api_profile_watchlist group by stock_id;
What is wrong with my annotation query?
You do too much joins. By joining twice over the many-to-many relation, you "blow up" the count.
You can simply count the amount of watchlists with that Stock
, with:
from django.db.models import Count
Stock.objects.annotate(
)
This works since, by default, the related_query_name=…
[Django-doc] has the name of the model (or the related_name
if you specified one). So the implicit relation you wrote from Stock
to Profile
(the reverse one of Profile
to Stock
in your watchlist
relation), is profile
(in lowercase). We thus ask Django to count, for a given Stock
object, the number of relations to a Profile
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.