Opened 2 years ago

Closed 8 months ago

#29145 closed Cleanup/optimization (wontfix)

Allow CIText values to be compared as the database would compare them (case-insensitively)

Reported by: Дилян Палаузов Owned by: Victor Munene
Component: contrib.postgres Version: 2.0
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Tim Graham)

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.

Change History (6)

comment:1 Changed 2 years ago 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?

comment:2 Changed 2 years ago 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.

comment:3 Changed 2 years ago by Jon Dufresne

A potentially related ticket is #28405. If CIText values had an __eq__, that might solve the ModelFormSet.validate_unique() issue.

comment:4 Changed 2 years ago by Tim Graham

Component: Uncategorizedcontrib.postgres
Description: modified (diff)
Summary: CIText and __eq__Allow CIText values to be compared as the database would compare them (case-insensitively)
Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization

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.

comment:5 Changed 8 months ago by Victor Munene

Owner: changed from nobody to Victor Munene
Status: newassigned
Last edited 8 months ago by felixxm (previous) (diff)

comment:6 Changed 8 months ago by felixxm

Resolution: wontfix
Status: assignedclosed

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.

Note: See TracTickets for help on using tickets.
Back to Top