Code

Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#18507 closed Uncategorized (worksforme)

Django 1.3 breaks ordering by the reverse of a one-to-one field

Reported by: vanschelven Owned by: nobody
Component: Database layer (models, ORM) Version: 1.3
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

I have a piece of code that breaks on migrating from 1.2 to 1.3. There is no mention of this in the 1.3 release notes, specifically in the section that speaks of backwards incompatibilities.

Basically, I'm poking the order_by value on User's Meta to be ordered by properties of UserProfile. UserProfile has a OneToOneField to user. On Django 1.2 this meant I could use UserProfile's fields for sorting Users. On Django 1.3 things start to break badly.

I.e.:

class UserProfile(models.Model):
    user = models.OneToOneField(User, editable=False)
    
    first_name = models.CharField(max_length=255, blank=True, verbose_name=_("Firstname"))
    name_prefix = models.CharField(max_length=50, blank=True, verbose_name=_("Lastname prefix"))
    last_name = models.CharField(max_length=255, blank=True, verbose_name=_("Lastname"))

    ...
    
User._meta.ordering = ('userprofile__last_name', 'userprofile__name_prefix', 'userprofile__first_name')

Django 1.2 situation:

>>> from django.contrib.auth.models import User
>>> u = User.objects.all()[0]
>>> User._meta.get_field_by_name('userprofile')
(<RelatedObject: userprofile:userprofile related to user>, None, False, False)
>>> 

Django 1.3 situation:

>>> from django.contrib.auth.models import User
>>> u = User.objects.all()[0]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  [...]
  File "/home/klaas/dev/online/demo/django/db/models/sql/query.py", line 1238, in setup_joins
    "Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'userprofile' into field. Choices are: ...
>>> User._meta.get_field_by_name('userprofile')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File ".../django/db/models/options.py", line 313, in get_field_by_name
    % (self.object_name, name))
FieldDoesNotExist: User has no field named 'userprofile'

The call to get_field_by_name is what goes wrong in the first place (i.e. it's the method call in setup_joins that's failing), so I've highlighted that above. I assume get_field_by_name() no longer existing for reverse fields might also cause breakage in certain applications, but haven't used it myself in a way that breaks.

I suppose it's not related to poking on User's Meta, and is a problem in general, but I haven't checked that yet.

Attachments (0)

Change History (3)

comment:1 Changed 2 years ago by vanschelven

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

In fact this is not restricted to Meta's ordering field but is also true for a "manual" call to ordering, i.e. removing ordering from Meta (whether poked or not) and calling:

User.objects.all().order_by("username__lastname")

comment:2 Changed 2 years ago by lukeplant

  • Resolution set to worksforme
  • Status changed from new to closed

I can't reproduce this on trunk or 1.4. It's possible it was a real bug but was fixed already. Please re-open if you can demonstrate this on trunk. (We wouldn't fix this on the 1.3.X branch, so there is no point me testing there).

comment:3 Changed 2 years ago by vanschelven

Turns out this was caused by #18510

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.