Context
I’m dealing with a legacy Oracle database with a column of type CHAR, which adds leading whitespaces on every query and it causes matching issues with the ORM (i.e. SomeModel.objects.filter(somefield="text")
can’t find some results because “text” != "text "). I got a a solution overriding from_db_value()
and get_db_prep_value()
method of Charfield (see below, on LegacyCharField) and it works pretty well in most of the cases except for iexact lookups.
Main Question
Some django builtin lookups (see django/db/models/lookups.py) like ‘exact’, ‘lt’, ‘gte’ has the FieldGetDbPrepValueMixin, which transforms the field value before sending to the database.
However, the lookup iexact doesn’t have FieldGetDbPrepValueMixin. That’s very odd and I can’t figure it why (maybe someone just forgot to add the mixin?). It is ok to add the mixin into the IExact lookup? Or should I take a different approach?
@Field.register_lookup
class IExact(BuiltinLookup):
...
My custom CharField:
class LegacyCharField(models.CharField):
def db_type(self, connection):
if connection.vendor == 'oracle':
return 'CHAR'
else:
return super().db_type(connection)
def from_db_value(self, value, expression, connection):
if connection.vendor == 'oracle':
if value is None:
return value
# Strip whitespaces
return value.rstrip()
else:
return value
def get_db_prep_value(self, value, connection, prepared=False):
value = super().get_db_prep_value(value, connection, prepared)
if connection.vendor == 'oracle':
if value is None:
return value
# Add whitespaces
return bytes(value, encoding='utf-8') \
.ljust(self.max_length) \
.decode(encoding='utf-8')
else:
return value