What is the correct way to do the following query:
sites = Site.objects.all().exclude(itempage__isnull=True or itempage__pk=1)
I would recommend using Django's Q Objects to construct more complex queries.
from django.db.models import Q
Site.objects.exclude(Q(itempage__isnull=True) | Q(itempage__pk=q))
Q objects also support negation with the ~ operator like so:
from django.db.models import Q
Site.objects.filter(~Q(Q(itempage__isnull=True) | Q(itempage__pk=q)))
Just wanted to another way of achieving this. Just chain the conditions using exclude().
sites = Site.objects.all().exclude(itempage__isnull=True).exclude(itempage__pk=1)
Related
Consider I have a model called Subject, and I want to filter the values based on the list of values.
Consider the below list.
["John", "Brad", None]
When I try to filter out the result using __in lookup it doesn't look for None values. For example
Subject.objects.filter(user__in=["John", "Brad", None])
This will provide the queryset for John and Brad but not None. What I'm missing here? Can anyone please help me
NULLs in DB (None in django) are not reqular values, so they need different approach:
Subject.objects.filter(Q(user__in=["John", "Brad", ]) | Q(user__isnull=True,))
Try filtering like this
from django.db.models import Q
Subject.objects.filter(Q(user__in=["John", "Brad"]) | Q(user__isnull=True))
Using Q objects is better suited for this:
Subject.objects.filter(Q(user__in=["John", "Brad"]) | Q(user__isnull=True))
You can use Q objects for OR, AND and NOT operations. Q objects provide you complete control over the where clause of the query.
Your queryset would be something like:
from django.db.models import Q
Subject.objects.filter(Q(user=None) | Q(user__in=["John", "Brad"]))
You can combine the Q objects in more complex ways to generate complex queries.
i'm try create or on filter on django
This is my little example :
products=Products.objects.values('name', 'price').all().filter(status=1|0)
The problem is that don't validate the two options (1|0)
don't get a error on the print(products.query) only validate one option don't the 2 options..!!
Please thanks !!
To filter using OR in django you need a special class called Q.
Documentation about Complex lookups with Q objects
from django.db.models import Q
products = Products.objects.values('name', 'price').filter(Q(status=1) | Q(status=0))
It's good to use Q object
manager.filter(Q(status=1) | Q(status=0))
You need to know that the method all() on a manager just delegates to get_queryset().
To use filter(), you would already have the QuerySet
Rather than all() whose calls the queryset, and then filter whose already call the queryset,
just do manager.filter()
all().filter() becomes just filter() because it's redundant
There it is:
from django.db.models import Q
products = Product.objects.values('name','price').filter(
Q(status=1) | Q(status=0),
)
Is there a mechanism to map Django QuerySet items not triggering its evaluation?
I am wondering about something like Python map. A function that uses a function to apply it over the QuerySet, but keeping the lazy evaluation.
For example, using models from Django documentation example, is there something like? (not real code):
>>> Question.objects.all().map(lambda q: q.pub_date + timedelta(hours=1))
which keeps the lazy evaluation?
Just working through something like this myself. I think the best way to do it is to use a python list comprehension.
[q.pub_date + timedelta(hours=1) for q in Question.objects.all()]
Then Django takes care of optimizing this as it would any other query.
You can use annotate for this purpose, for example
from datetime import timedelta
from django.db.models import F, ExpressionWrapper, DateTimeField
Question.objects.annotate(
new_pub_date=ExpressionWrapper(
F('pub_date') + timedelta(hours=1),
output_field=DateTimeField()
)
)
For something a little bit more complex than this example, you can use Func, Case, When
You can use values_list to get any column you like:
Question.objects.values_list('pub_date')
This is simpler than anything you can cook up yourself.
So I want to find any kind of matching given some fields, so for example, this is what I would like to do:
possible_merchants = ["amazon", "web", "services"]
# Possible name --> "Amazon Service"
Companies.objects.filter(name__icontains__in=possible_merchants)
sadly it is not possible to mix icontains and the __in lookup.
It seems to be a pretty complex query so if at least I could ignore case the name that would be enough, for example:
Companies.objects.filter(name__ignorecase__in=possible_merchants)
Any ideas?
P.D.: The queries I posted don't work, it's just a way to express what I need (just in case heh)
You can create querysets with the Q constructor and combine them with the | operator to get their union:
from django.db.models import Q
def companies_matching(merchants):
"""
Return a queryset for companies whose names contain case-insensitive
matches for any of the `merchants`.
"""
q = Q()
for merchant in merchants:
q |= Q(name__icontains = merchant)
return Companies.objects.filter(q)
(And similarly with iexact instead of icontains.)
I find it a cleaner approach using reduce and or_ operator:
from django.db.models import Q
from functools import reduce
from operator import or_
def get_companies_from_merchants(merchant_list):
q_object = reduce(or_, (Q(name__icontains=merchant) for merchant in merchant_list))
return Companies.objects.filter(q_object)
This would create a list of Q objects querying the name to contain a single element in merchant list. This would happpen for all the elements in merchant_list and all these Q objects would be reduced to a single Q object having mutliple ORs which can be directly applied to the filter query.
This is the approach that I adopted:
class MyManager(models.Manager):
def exclusive_in(self, lookup, value_list):
return self.filter(reduce(or_, (Q(**{lookup:_}) for _ in value_list)))
Here is now to use it:
Companies.objects.exclusive_in('name__icontains', possible_merchants])
It was inspired by other answers in this thread, as well as Django filter queryset __in for *every* item in list.
Another approach would be to simulate the actions that Django normally does for iexact queries (it converts both parts of the comparison statement to the upper case via SQL Upper function.
This way, the query will look like this:
Companies.objects.annotate(
upper_name=models.Upper("name")
).filter(
upper_name__in=[rchant.upper() for merchant in possible_merchants]
)
I have a very simple query: select * from tbl1 where title not in('asdasd', 'asdasd').
How do I translate that to Django? It's like I want the opposite of: Table.objects.filter(title__in=myListOfTitles)
try using exclude
Table.objects.exclude(title__in=myListOfTitles)
(this thread is old but still could be googled)
you can use models.Q with "~" as follows:
Table.objects.filter(~Q(title__in=myListOfTitles))
this method specially is helpful when you have multiple conditions.
Table.objects.exclude(title__in=myListOfTitles)
Django provides two options.
exclude(<condition>)
filter(~Q(<condition>))
Method 2 using Q() method
>>> from django.db.models import Q
>>> queryset = User.objects.filter(~Q(id__lt=5))