Django

Code

Ticket #2210 (closed: duplicate)

Opened 2 years ago

Last modified 1 year ago

[patch] order_by on related table with db_column different to name fails

Reported by: Russell Cloran <russell@hbd.com> Assigned to: adrian
Milestone: Component: Database wrapper
Version: SVN Keywords: order_by related
Cc: bs1984@gmail.com, russell@rucus.net, gary.wilson@gmail.com, real.human@mrmachine.net, arthur.case@gmail.com Triage Stage: Accepted
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

Hi,

When ordering by a related table which has a db_column different to the field name, and ordering by the field name, incorrect SQL is generated.

This bug is on line 483 of django/db/models/query.py (r3189) -- it incorrectly uses the opts of the main table, not the related table in the call to orderfield2column(). This shows up in the admin interface, when sorting by a related field.

I do not know the correct fix for this bug.

Russell

Attachments

order_by_related.diff (2.1 kB) - added by serbaut@gmail.com on 09/09/06 09:56:24.
Patch for order_by related fields
ticket-2210.diff (4.3 kB) - added by mir@noris.de on 01/24/07 12:31:27.
revised and updated patch
models1.py (1.9 kB) - added by ramiro <rm0 _at_ gmx.net> on 02/02/07 21:09:19.
models2.py (1.9 kB) - added by ramiro <rm0 _at_ gmx.net> on 02/02/07 21:13:00.

Change History

06/21/06 13:27:05 changed by Russell Cloran <russell@hbd.com>

  • cc set to russell@hbd.com.

06/21/06 17:00:47 changed by ramiro

A similar report was made in #2076, also #2121 may be related too?

06/22/06 02:13:55 changed by Russell Cloran <russell@hbd.com>

This is a different bug to #2076, fwict. The joins are being correctly generated in my case, but the wrong column name is being used.

07/03/06 06:41:52 changed by Russell Cloran <russell@hbd.com>

  • cc changed from russell@hbd.com to russell@rucus.net.

09/09/06 09:56:24 changed by serbaut@gmail.com

  • attachment order_by_related.diff added.

Patch for order_by related fields

09/09/06 10:00:00 changed by serbaut@gmail.com

  • summary changed from order_by on related table with db_column different to name fails to [patch] order_by on related table with db_column different to name fails.

I added a patch that allows you to do order by related fields.

Foo.objects.all().order_by('name')
Bar.objects.order_by('-foo__name')
Baz.objects.order_by('bar__foo__name')

The Admin interface needs to be updated to make use of this.

11/09/06 09:28:31 changed by Gary Wilson <gary.wilson@gmail.com>

  • cc changed from russell@rucus.net to russell@rucus.net, gary.wilson@gmail.com.

11/16/06 19:11:04 changed by mrmachine <real dot human at mrmachine dot net>

  • cc changed from russell@rucus.net, gary.wilson@gmail.com to russell@rucus.net, gary.wilson@gmail.com, real.human@mrmachine.net.

01/04/07 02:47:09 changed by anonymous

  • cc changed from russell@rucus.net, gary.wilson@gmail.com, real.human@mrmachine.net to russell@rucus.net, gary.wilson@gmail.com, real.human@mrmachine.net, arthur.case@gmail.com.

01/24/07 12:31:27 changed by mir@noris.de

  • attachment ticket-2210.diff added.

revised and updated patch

01/24/07 12:36:28 changed by mir@noris.de

  • needs_tests set to 1.
  • stage changed from Unreviewed to Accepted.

The orignal patch failed to support order_by('?'), though it tried to handle it twice. I've revised it, and now it passes all tests. It still needs additional tests to demonstrate that order_by('xxx_yyy') works now. Thanks, serbaut, for the original patch, I didn't really have to do a lot ;-)

01/24/07 12:46:45 changed by mir@noris.de

marked #2076, #3248, #1616 marked as duplicates.

Regarding the tests, please write tests for both directions (asc/desc)

01/26/07 05:05:11 changed by bram.Dejong+djangotrac@gmail.com

  • keywords set to order_by related.

This bug is confirmed. Here's a complete example to reproduce the problem:

models.py

from django.db import models

class Book(models.Model):
	title = models.TextField()

class BookStat(models.Model):
	book = models.OneToOneField(Book, related_name='stats')
	times_read = models.PositiveIntegerField()

After syncing the DB, in the command line:

 >>> from orderby.example.models import *
 >>> book = Book.objects.create(title="BFG")
 >>> book.save()
 >>> bs = BookStat.objects.create(book=book, times_read=15)
 >>> bs.save()
 >>> Book.objects.all().order_by("stats__times_read")
Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "C:\Python25\lib\site-packages\django\db\models\query.py", line 101, in __repr__
     return repr(self._get_data())
   File "C:\Python25\lib\site-packages\django\db\models\query.py", line 444, in _get_data
     self._result_cache = list(self.iterator())
   File "C:\Python25\lib\site-packages\django\db\models\query.py", line 181, in iterator
     cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
   File "C:\Python25\lib\site-packages\django\db\backends\util.py", line 12, in execute
     return self.cursor.execute(sql, params)
   File "C:\Python25\lib\site-packages\django\db\backends\postgresql\base.py", line 43, in execute
     return self.cursor.execute(sql, [smart_basestring(p, self.charset) for p in params])
ProgrammingError: ERROR:  column example_book.stats__times_read does not exist at character 80
SELECT "example_book"."id","example_book"."title" FROM "example_book" ORDER BY "example_book"."stats__times_read" ASC

02/01/07 05:05:40 changed by bram.Dejong+djangotrac@gmail.com

I just found out exactly the same error happens in this case:

from django.db import models

class Book(models.Model):
	title = models.TextField()

class BookStat(models.Model):
	book = models.OneToOneField(Book)
	times_read = models.PositiveIntegerField()

Book.objects.all().order_by("bookstat__times_read")

I.e. can't sort by a one-to-one field in another model.

  • bram

02/01/07 07:00:13 changed by bram.Dejong+djangotrac@gmail.com

The patch breaks on:

{{ queryset.extra(select={'squeek': "......"}).order_by("-squeek") }}

resulting in the error:

Cannot resolve keyword 'comment_count' into field

02/01/07 07:01:00 changed by bram.Dejong+djangotrac@gmail.com

  • needs_better_patch set to 1.

02/01/07 07:31:15 changed by Michael Radziej <mir@noris.de>

Can you please post your models and the full traceback? How does 'comment_count' get into it?

02/01/07 07:47:01 changed by Michael Radziej <mir@noris.de>

May be this is related to #3355?

02/01/07 07:49:18 changed by Michael Radziej <mir@noris.de>

Bram, can you please also send in the full sql statement that was sent to the database? queryset._get_sql_clause() can do this trick if it isn't visible elsewhere.

02/02/07 03:13:21 changed by anonymous

Sorry, comment_count should have been "squeek".

That said, I had to un-apply the patch and work with the extra( ) to get it all working without the patch as I'm on a very tight deadline. However here's what I found the last time:

Models:

from django.db import models

class Book(models.Model):
    title = models.TextField()

class BookStat(models.Model):
    book = models.OneToOneField(Book)
    times_read = models.PositiveIntegerField()

class BookRating(models.Model):
    book = models.ForeignKey(Book)
    rating = models.PositiveIntegerField()

Shell:

from example.models import *
 
bfg = Book.objects.create(title="bfg")
bfg.save()
matilda = Book.objects.create(title="matilda")
matilda.save()
 
BookRating.objects.create(book=bfg, rating=5).save()
BookRating.objects.create(book=bfg, rating=8).save()
BookRating.objects.create(book=bfg, rating=15).save()
BookRating.objects.create(book=matilda, rating=15).save()
BookRating.objects.create(book=matilda, rating=16).save()
BookRating.objects.create(book=matilda, rating=17).save()
BookStat.objects.create(book=bfg, times_read=5).save()
BookStat.objects.create(book=matilda, times_read=3).save()

# works with patch:
qs = Book.objects.all().order_by("stats__times_read")

# the equivalent, works without patch, same result
qs = qs.extra(where=["example_book.id = example_bookstat.book_id"], tables=["example_bookstat"]).order_by("-example_bookstat.times_read")

# works WITHOUT patch, breaks with patch 
qs = Book.objects.all().extra(select={ 'avg_rating': 'SELECT avg(rating) FROM example_bookrating WHERE example_bookrating.book_id = example_book.id'}).order_by("-avg_rating")

Right now I can't do the stack-trace as I would have to re-apply the patch...

For people looking into these problems, this is a workaround for the initial problem described in the ticket:

02/02/07 08:54:52 changed by anonymous

  • cc changed from russell@rucus.net, gary.wilson@gmail.com, real.human@mrmachine.net, arthur.case@gmail.com to bs1984@gmail.com, russell@rucus.net, gary.wilson@gmail.com, real.human@mrmachine.net, arthur.case@gmail.com.

02/02/07 11:24:46 changed by Michael Radziej <mir@noris.de>

  • needs_better_patch deleted.
  • has_patch deleted.
  • needs_tests deleted.
  • stage changed from Accepted to Unreviewed.

**OUCH**

The first two patches and the later comments (beginning with comment 9) actually belong to #2076.

See thread in django-developers

Thank you for digging this up, Ramiro Gonzales.

02/02/07 21:08:05 changed by ramiro <rm0 _at_ gmx.net>

So, it seems the patch for #2076 also solves this ticket :-/

Attached you will find a models1.py, it has some doctest [1]testcases that reproduce the problem described by the original reporter. It should be installed as the models.py file of a ticket2210 application.

Also attached is a models2.py, it has the same [1]testcases but using the order_by notation introduced by the patch for #2076 (so that patch should be applied first) and they complete without errors. It should be installed as the app models.py file.

Apologies for the noise.

1. Run them executing

$ ./manage.py test ticket2210

02/02/07 21:09:19 changed by ramiro <rm0 _at_ gmx.net>

  • attachment models1.py added.

02/02/07 21:13:00 changed by ramiro <rm0 _at_ gmx.net>

  • attachment models2.py added.

02/02/07 22:46:14 changed by Gary Wilson <gary.wilson@gmail.com>

  • stage changed from Unreviewed to Accepted.

02/19/07 18:52:34 changed by mtredinnick

  • status changed from new to closed.
  • resolution set to duplicate.

Closing this as a duplicate of #2076, since that ticket has a fairly good patch and test cases.


Add/Change #2210 ([patch] order_by on related table with db_column different to name fails)




Change Properties
Action