Opened 5 years ago

Closed 5 years ago

#22843 closed Uncategorized (wontfix)

contrib.auth.models.User not comparable

Reported by: ukl Owned by: nobody
Component: Uncategorized Version: 1.6
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Russell Keith-Magee)

I stumbled over User objects not being comparable as expected in Python code. While I can order by the related User object in a query just fine this fails when sorting in Python.

The reason can be seen in the following manage.py shell session:

>>> from django.contrib.auth.models import User

>>> u1 = User.objects.get(id=1)

>>> u2 = User.objects.get(id=2)

>>> u1_ = User.objects.get(id=1)

>>> u1 < u2
>>> True

>>> u2 < u1_
>>> True

>>> u1 < u1_
>>> True

>>> u1 == u1_
>>> True

I think < compares using the object address while == uses the id attribute to compare.

A more complex example that shows the failure is:

>>> sum(1 for _ in groupby(map(attrgetter('user'), MyModel.objects.order_by('user'))))
16
>>> sum(1 for _ in groupby(map(attrgetter('user'), sorted(MyModel.objects.all(), key=attrgetter('user')))))
90

This means that in the first example there are 16 unique related Users in the MyModel objects. The second line finds considerably more Users because the sorting fails and so groupby doesn't detect duplicates.

I expected that both iterators MyModel.objects.order_by('user') and sorted(MyModel.objects.all(), key=attrgetter('user')) yield the same ordering.

Change History (1)

comment:1 Changed 5 years ago by Russell Keith-Magee

Description: modified (diff)
Resolution: wontfix
Status: newclosed

It isn't clear to me at all why this is the behaviour your would expect. No other Python object has an automatic and implied ordering on an arbitrary attribute, and there's nothing on the User model to say that "username" is the best attribute for this ordering (and I presume you meant "username", not "user"). The default User model doesn't have any predefined ordering defined. The order returned by the database is unpredictable (although, for small data sets, it will generally match the order of database insertion).

In theory, I suppose it would be possible for any object with an ordering defined to automatically gain a __cmp__ method that implements that search order. However, I'm not sure I agree that this sort of implicit behaviour would be desirable. It would also be complicated to implement in a way that doesn't override manually defined __cmp__ methods on a model.

It would also be possible to make a special case of the User object and manually define a __cmp__ method specifically for User; however, that would also act as an encouragement for people to do sorting in Django, rather than in the database (where the operation can be optimised).

So - marking this wontfix. If you want to argue for this change, please start a thread on django-developers.

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