Reputation: 6280
Is it possible to add an additional raw sql clause to a django queryset?
Preferably with the RawSQL
clause to a normal queryset.
It should be a normal queryset and not a rawqueryset because I want to use it in the django admin.
In my particular case I want to add an additonal exists
where clause:
and exists (
select 1
from ...
)
In my concrete case I have two models Customer
and Subscription
. The Subscription
has a start
and optional end
date field.
I want to have a queryset with all customers which have a current subscription today. Like this SQL query:
select *
from customers_customer c
where exists (
select 1
from subscriptions_subscription sc
where sc.customer_id = c.id
and sc.start < current_date
and (sc.end is null or sc.end > current_date)
)
I was not able to make a queryset out of this. The best thing I arrived, was something like:
cs = Customer.objects.annotate(num_subscriptions=RawSQL(
'''
select count(sc.id)
from subscriptions_customersubscription sc
where sc.customer_id = customers_customer.id
and sc.start < current_date
and (sc.end is null or sc.end > current_date)
''', []
))
But this query does not perform as well as the SQL-query with the where exists
.
Upvotes: 1
Views: 2164
Reputation: 1112
In answer to the original question, one can use the QuerySet.extra()
method to add raw SQL as explained in the docs
Upvotes: 0
Reputation: 1473
Not answering your question, but you can query customers like this:
from django.db.models import Q
Customer.objects.filter(
Q(subscription__start__lt=current_date),
Q(subscription__end=None) | Q (subscription__end__gt=current_date)
).distinct()
Upvotes: 2