Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ORM: MyModel.objects.filter(name__iexact__in=[...])

Tags:

django-orm

I have a list of strings and I would like to do an case-insensitive "in" lookup with Django ORM.

I know, that I can do this:

name_list = ['Alpha', 'bEtA', 'omegA']
q_list = map(lambda n: Q(name__iexact=n), name_list)
q_list = reduce(lambda a, b: a | b, q_list)
MyModel.objects.filter(q_list)

But maybe there is a simpler solutions with more modern Django ORM?

like image 702
guettli Avatar asked Jun 20 '18 10:06

guettli


People also ask

Why are QuerySets considered lazy?

This is because a Django QuerySet is a lazy object. It contains all of the information it needs to populate itself from the database, but will not actually do so until the information is needed.

How do I make multiple rows in Django?

To create multiple records based on a Django model you can use the built-in bulk_create() method. The advantage of the bulk_create() method is that it creates all entries in a single query, so it's very efficient if you have a list of a dozen or a hundred entries you wish to create.

What is F in Django ORM?

In the Django QuerySet API, F() expressions are used to refer to model field values directly in the database.

How do I use ORM in Django?

To do so, open the Django shell to run the query. You might be wonder how Django ORM makes our queries executed or what the corresponding query of the code we are writing. It is quite simple to get the SQL query, we need to use the str() and pass the queryset object along with query.


1 Answers

IN operator(and other MySQL operators except binary comparisons) are case insensitive by default, unless you have changed the table collation. In most of the cases, you can simply use MyModel.objects.filter(name__in=name_list).

See https://blog.sqlauthority.com/2007/04/30/case-sensitive-sql-query-search/ to know more about collation.

P.S. Avoid using map-reduce like this. If the name_list length is large enough, your entire mysql-server can get down.

Edit:

For PostgreSQL you can do the following: MyModel.objects.annotate(name_lower=Lower('name')).filter(name_lower__in=[name.lower() for name in name_list])

like image 74
tahmed1994 Avatar answered Oct 21 '22 04:10

tahmed1994