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)
Definition and Usage. The icontains lookup is used to get records that contains a specified value. The icontains lookup is case insensitive. For a case sensitive search, use the contains lookup.
Definition and Usage The contains lookup is used to get records that contains a specified value. The contains lookup is case sensitive. For a case insensitive search, use the icontains lookup.
Django offers a QuerySet method called select_related() that allows you to retrieve related objects for one-to-many relationships. This translates to a single, more complex QuerySet, but you avoid additional queries when accessing the related objects. The select_related method is for ForeignKey and OneToOne fields.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With