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?
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.
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.
In the Django QuerySet API, F() expressions are used to refer to model field values directly in the database.
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.
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])
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