Hey!
I’m writing an “API” for one of my app so that other users can run some queries against the model without having direct access to the service / database.
One of the ways I’m trying to make this “easier” on the user is to have most filtering being case-insensitive. And I need both a filter
and an exclude
version of this.
My understanding is that the official stance of Django for now is that having a iin
(similar to iexact
or iregex
, …) is not deemed useful.
The solution I’ve found online is to do something like this:
from django.db.models.functions import Lower
Model.objects.annotate(lowercase=Lower("field")).filter(lowercase__in=["Value1", "Value2"])
and this seem to work. But the exclude
version fails in an unexpected way.
Namely, when the field is nullable, and results in a None value, it’s being discarded.
Model.objects.annotate(lowercase=Lower("field")).exclude(lowercase__in=["Value1".lower(), "Value2".lower()])
results in any record where field
is null
(and as a result Lower("field")
to also be) to just not return here. Which is not my expectation. As the “normal” ...exclude(field__in=["value1"])
does return these records.
Any idea of what I’m doing wrong?
Thank you
PS: In my app, field
is actually a foreign key so it looks more like lowercase=Lower("foreignkey__name")
. But from my testing the ForeignKey is not the differentiator here. I get the exact same result on a CharField
that has None
values.