Under the premise that python and postgresql use the same collation, tweak
the system to compare two citext-fields in a case-insensitive manner for
equality, without touching the database (as it is done for all other
fields).
Attaching to each citext-field returned from the model an {{{__eq__}}}
doing {{{.lower()}}} could help.
--
Ticket URL: <https://code.djangoproject.com/ticket/29145>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Simon Charette):
Model equality (`Model.__eq__`) is determined by the `type(instance),
instance.pk` tuple and not by the value of its other fields. That makes
`Foo(id=1, field='bar') == Foo(id=1, field='baz')`.
Are you talking about your own version of model equality?
--
Ticket URL: <https://code.djangoproject.com/ticket/29145#comment:1>
Comment (by Дилян Палаузов):
I am not talking about model equality, but about a field equality.
The use case is a list of models-instances without IDs and the list can
contain the same instance several times. I want to send a single SELECT
and assign IDs to all objects in the list.
However, the list can contains twice the same object while the SELECT will
return the object only once. Moreover the objects are returned in any
order. So the result of SELECT needs to be matched with the objects from
the list, comparing field-by-field of what was requested if it matches the
currently processed row. For this matching to work universally with == in
case CICharField fields 'a' == 'A' must also match.
--
Ticket URL: <https://code.djangoproject.com/ticket/29145#comment:2>
Comment (by Jon Dufresne):
A potentially related ticket is #28405. If CIText values had an `__eq__`,
that might solve the `ModelFormSet.validate_unique()` issue.
--
Ticket URL: <https://code.djangoproject.com/ticket/29145#comment:3>
* type: Uncategorized => Cleanup/optimization
* component: Uncategorized => contrib.postgres
* stage: Unreviewed => Accepted
Old description:
> For comparing two model instances on equality one can iterate over all
> fields in the instance and compare the fields for equality, without
> querying the database. This does not work for
> django.contrib.postgres.fields.citext.CIText, where "a" is equal to "A".
>
> Under the premise that python and postgresql use the same collation,
> tweak the system to compare two citext-fields in a case-insensitive
> manner for equality, without touching the database (as it is done for all
> other fields).
>
> Attaching to each citext-field returned from the model an {{{__eq__}}}
> doing {{{.lower()}}} could help.
New description:
For comparing two model instances on equality one can iterate over all
fields in the instance and compare the fields for equality, without
querying the database. This does not work for
django.contrib.postgres.fields.citext.CIText, where "a" is equal to "A".
Under the premise that python and postgresql use the same collation, tweak
the system to compare two citext-fields in a case-insensitive manner for
equality, without touching the database (as it is done for all other
fields).
Attaching to each citext-field returned from the model an `__eq__` doing
`.lower()` could help.
--
Comment:
Tentatively accepting, although I'm not certain about the complexity this
will require. I'm thinking that whenever a value is assigned to a CI
field, that value will be have to wrapped in a `str` subclass that
implements `__eq__()` to do the case-insensitive comparison. I guess a
perfect implementation that considers database collation, for example, may
not be feasible.
--
Ticket URL: <https://code.djangoproject.com/ticket/29145#comment:4>
* owner: nobody => Victor Munene
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/29145#comment:5>
* status: assigned => closed
* resolution: => wontfix
Comment:
The proposed solution is error-prone and can be confusing. Moreover I
don't think that we will be able to provide a better one.
--
Ticket URL: <https://code.djangoproject.com/ticket/29145#comment:6>