I would like to know how to frame the following to the Django ORM form:
SELECT name,mobile_number,COUNT(*) as count, created FROM core_user,core_useractivity WHERE core_user.id = core_useractivity.user_id GROUP BY user_id ORDER BY count DESC;
where name, mobile number are columns in core_user table or USER model, and created is a column in core_useractivity its model is UserActivity . The two tables are joined on user_id. Further I am grouping the rows by user_id displaying the result in Descending order.
Try annotating the users with the user activity count.
from django.db.models import Count
User.objects.annotate(num_activities=Count('useractivity')).order_by('num_activities')
This will return a queryset of users, each with an attribute num_activities. See the docs on annotation for more information.
Related
How can i make an efficient django orm query, which will compare ids from the list of dictionaries with the ids as foreign key in other model, e.g i have two models
Product:
product_name=models.CharField(max_length=20)
ProductOrder:
order_status=models.BooleanField()
product=models.ForeignKey(Product,on_delete=models.CASCADE)
now i want extract every product which is present in product order.
in simple query i can do this way:
prod=ProductOrder.objects.all()
products=Product.objects.all()
for prod in prod:
for products in products:
if prod.product==products.id:
# save product
Is there any way to get this through one query or more efficiently?
You can filter with:
products = Product.objects.filter(productorder__isnull=False).distinct()
Here products is a QuerySet of Products for which there is at least one related ProductOrder.
This works because we make a LEFT OUTER JOIN on the ProductOrder table and then check if that ProductOrder is not NULL. We use .distinct() [Django-doc] to prevent retrieving a Product that many times as there are ProductOrders. Likely the Django ORM will notice the __isnull=False constraint, and optimize this to an INNER JOIN.
I have three tables:
Table 1 : order
Fields: id, client_reference, price and status
(status is a foreignkey linked to order_status.id)
Table 2 : order_status
Fields: id, lastupdate
Table 3 : order_status_i18n
Fields: id, order_status_id, language and label
(order_status_id is also a foreignkey linked to order_status.id)
what I'd like to do is to get the order_status_i18n label instead of order_status_id based on the user language, so the SQL request would be like:
SELECT o.client_reference as reference, o_s_i18n.label
FROM
order AS o
INNER JOIN order_status_i18n AS o_s_i18n
ON o.status=o_s_i18n.order_status_id WHERE o_s_i18n.language='the language';
and the Model for order contains a foreignkey attribute linked to the order_status model but not order_status_i18n, so I tried to use
Order.objects.filter(some_filters).prefetch_related('status')
.filter(status__in=OrderStatusI18N.objects.filter(language='the_language'))
Which gives me a queryset conflict telling me that I should use the queryset for OrderStatus rather than OrderStatusI18N and I totally agree to this.
But anyway, what would be the good way to manage such a request using django ORM?
I think this should do the thing.
Order.objects.filter(some_filters).prefetch_related('status').annotate(i18_label=F('status__order_status_i18n__language')).filter(status__order_status_i18n__language='en')
In Django, I have a User model and a Following model:
class User():
uid = models.UUIDField(primary_key=True)
class Following():
follower_uid = models.ForeignKey(USER_MODEL, related_name="followers")
followed_uid = models.ForeignKey(USER_MODEL, related_name="following")
with corresponding database tables for both object types.
When Django loads a User object, I want to also load the number of followers of that user in the same database query, i.e. using a join. What I don't want to do is load the user first and then do a second query to get the number of followers.
Is this possible using the Django object model or do I have to write raw sql?
I also want to load a second-degree count; that is, the number of followers of the followers of the user. As before, I want this count to be loaded in the same database query as the user itself.
Appreciate specific syntax and examples, I have read a ton of Django documentation and nothing seems to answer this. Thanks!
you can do this query:
from django.db.models import Count
>>> user = User.objects.filter(pk=some_id).annotate(num_followers=Count('followers'))
>>> user
[<User: someuser>]
>>> user[0].id
some_id
>>> user[0].num_followers
123
i want to use django models feature to excute this sql query.
SELECT COUNT(DISTINCT ques_id), title FROM contest_assignment WHERE grp_id = 60 GROUP BY title;
i tried this but it did not give me proper result:
from django.db.models import Count
assignment.objects.values_list('title').annotate(count=Count('ques')).values('title', 'count')
how can i use django model?
You shouldn't use both .values() and .values_list(). The count field is implicitly added to the set of fields that is returned.
Django supports a COUNT(DISTINCT <field>) query by using .annotate(count=Count('<field>', distinct=True)). That would leave you with the following query:
(assignment.objects.filter(grp_id=60).values('title')
.annotate(count=Count('ques_id', distinct=True)))
I run a lab annotation website where users can annotate samples with tags relating to disease, tissue type, etc. Here is a simple example from models.py:
from django.contrib.auth.models import User
from django.db import models
class Sample(models.Model):
name = models.CharField(max_length = 255)
tags=models.ManyToManyField('Tag', through = 'Annot')
class Tag(models.Model):
name = models.CharField(max_length = 255)
class Annot(models.Model):
tag = models.ForeignKey('Tag')
sample = models.ForeignKey('Sample')
user = models.ForeignKey(User, null = True)
date = models.DateField(auto_now_add = True)
I'm looking for a query in django's ORM which will return the tags in which two users agree on the annotation of same tag. It would be helpful if I could supply a list of users to limit my query (if someone only believes User1 and User2 and wants to find the sample/tag pairs that only they agree on.)
I think I understood what you need. This one made me think, thanks! :-)
I believe the equivalent SQL query would be something like:
select t.name, s.name, count(user_id) count_of_users
from yourapp_annot a, yourapp_tag t, yourapp_sample s
where a.tag_id = t.id
and s.id = a.sample_id
group by t.name, s.name
having count_of_users > 1
While I try hard not to think in SQL when I'm coming up with django model navigation (it tends to get in the way); when it comes to aggregation queries it always helps me to visualize what the SQL would be.
In django we now have aggregations.
Here is what I came up with:
models.Annot.objects.select_related().values(
'tag__name','sample__name').annotate(
count_of_users=Count('user__id')).filter(count_of_users__gt=1)
The result set will contain the tag, the sample, and the count of users that tagged said sample with said tag.
Breaking it apart for the folks that are not used to django aggregation:
models.Annot.objects.select_related()
select_related() is forcing all tables related to Annot to be retrieved in the same query
This is what will allow me to specify tag__name and sample__name in the values() call
values('tag__name','sample__name')
values() is limiting the fields to retrieve to tag.name and sample.name
This makes sure that my aggregation on count of clients will group by just these fields
annotate(count_of_users=Count('user__id'))
annotate() adds an aggregation as an extra field to a query
filter(count_of_users__gt=1)
And finally I filter on the aggregate count.
If you want to add an additional filter on what users should be taken into account, you need to do this:
models.Annot.objects.filter(user=[... list of users...]).select_related().values(
'tag__name','sample__name').annotate(
count_of_users=Count('user__id')).filter(count_of_users__gt=1)
I think that is it.
One thing... Notice that I used tag__name and sample__name in the query above. But your models do not specify that tag names and sample names are unique.
Should they be unique? Add a unique=True to the field definitions in the models.
Shouldn't they be unique? You need to replace tag__name and sample__name with tag__id and sample__id in the query above.