Request Method: POST
Request URL: http://192.168.3.200:8001/orders/price/
Django Version: 1.7b1
Python Executable: /home/ic/adk/dj/bin/python
Python Version: 2.7.3
Python Path: ['/home/ic/adk/dj/adkwoningdev',
'/home/ic/adk/dj/lib/python2.7/site-
packages/adkw_calctable-0.1-py2.7.egg', '/home/ic/adk/dj/lib/python2.7
/site-packages/adkw_portsectionheights-0.1-py2.7.egg',
'/home/ic/adk/dj/lib/python27.zip', '/home/ic/adk/dj/lib/python2.7',
'/home/ic/adk/dj/lib/python2.7/plat-linux2',
'/home/ic/adk/dj/lib/python2.7/lib-tk', '/home/ic/adk/dj/lib/python2.7
/lib-old', '/home/ic/adk/dj/lib/python2.7/lib-dynload',
'/opt/python-2.7.3/lib/python2.7', '/opt/python-2.7.3/lib/python2.7/plat-
linux2', '/opt/python-2.7.3/lib/python2.7/lib-tk',
'/home/ic/adk/dj/lib/python2.7/site-packages',
'/home/ic/adk/dj/lib/python2.7/site-packages/PIL']
Server time: Thu, 17 Apr 2014 12:10:24 +0200
Installed Applications: ('django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.sites', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.admin',
'django.contrib.admindocs', 'south', 'orders', 'siunits', 'portsections',
'springcalc', 'ral', 'printer', 'springorders', 'glassorders',
'suppliers', 'scanner', 'statistics', 'django_extensions', 'panels',
'tracks', 'drive', 'person', 'discounts', 'production',
'productionplanning', 'nonstdports', 'unstructuredorders', 'adkapp5',
'loading', 'paints', 'deliverynote', 'mail', 'download', 'experiments')
Installed Middleware: ('django.middleware.gzip.GZipMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'mymid.CustomMiddleware')
Traceback: File "/home/ic/adk/dj/lib/python2.7/site-
packages/django/core/handlers/base.py" in get_response 113. response =
wrapped_callback(request, *callback_args, **callback_kwargs) File
"/home/ic/adk/dj/lib/python2.7/site-
packages/django/contrib/auth/decorators.py" in _wrapped_view 22. return
view_func(request, *args, **kwargs) File
"/home/ic/adk/dj/adkwoningdev/orders/views.py" in price 161. price =
order.get_price_estimate() File
"/home/ic/adk/dj/adkwoningdev/orders/models.py" in get_price_estimate
1473. return self.count *
self.process_order_items(self.price_item_discount) File
"/home/ic/adk/dj/adkwoningdev/orders/models.py" in process_order_items
1198. price, panel = self.calculate_panelprice() File
"/home/ic/adk/dj/adkwoningdev/orders/models.py" in calculate_panelprice
1570. if len(panels) > 0: File "/home/ic/adk/dj/lib/python2.7/site-
packages/django/db/models/query.py" in __len__ 122. self._fetch_all() File
"/home/ic/adk/dj/lib/python2.7/site-packages/django/db/models/query.py" in
_fetch_all 961. self._result_cache = list(self.iterator()) File
"/home/ic/adk/dj/lib/python2.7/site-packages/django/db/models/query.py" in
iterator 265. for row in compiler.results_iter(): File
"/home/ic/adk/dj/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in results_iter 694. for rows
in self.execute_sql(MULTI): File "/home/ic/adk/dj/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in execute_sql 769. sql, params
= self.as_sql() File "/home/ic/adk/dj/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in as_sql 100. ordering,
o_params, ordering_group_by = self.get_ordering() File
"/home/ic/adk/dj/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in get_ordering 424.
self.query.get_meta(), default_order=asc): File
"/home/ic/adk/dj/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in find_ordering_name 464. if
field.rel and path and opts.ordering: Exception Type: AttributeError at
/orders/price/ Exception Value: 'ManyToOneRel' object has no attribute
'rel'
--
Ticket URL: <https://code.djangoproject.com/ticket/22466>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* needs_docs: => 0
* resolution: => needsinfo
* needs_tests: => 0
* needs_better_patch: => 0
Comment:
Hi,
Could you show your model definitions and the code you're using to trigger
this error (if you could reduce this error to a short snippet of code,
that would also really help in reproducing it)?
Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:1>
Comment (by takis):
Hi,
The codebase is large, so I will try to extract the smallest possible
amount of code which still triggers the error. I cannot do it right away
though, but I'll try to have a go after work this evening or tomorrow
evening.
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:2>
Comment (by takis):
Hi,
I finally found the time to minimize the application code, and track down
the problem.
{{{#!python
from django.db import models
class Article(models.Model):
code = models.CharField(max_length=64, unique=True)
description = models.CharField(max_length=256, blank=True)
class Price(models.Model):
article = models.ForeignKey('Article', null=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
}}}
{{{#!python
import logging
from django.http import HttpResponse
from orders.models import Article
def testbug(request):
objs = Article.objects.all().order_by('price')
logging.debug("len articles: %d", len(objs))
return HttpResponse("")
}}}
{{{#!python
from django.conf.urls import patterns, url
urlpatterns = patterns('',
url(r'^orders/', 'orders.views.testbug'),
)
}}}
{{{#!python
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
SECRET_KEY = 'xyz'
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'orders',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'adkw.urls'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
}}}
{{{
Environment:
Request Method: GET
Request URL: http://localhost:8001/orders/
Django Version: 1.7b3
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'orders')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Traceback:
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/core/handlers/base.py" in get_response
113. response = wrapped_callback(request,
*callback_args, **callback_kwargs)
File "/home/ic/test/bug2/adkw/orders/views.py" in testbug
7. logging.debug("len articles: %d", len(objs))
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/query.py" in __len__
122. self._fetch_all()
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/query.py" in _fetch_all
961. self._result_cache = list(self.iterator())
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/query.py" in iterator
265. for row in compiler.results_iter():
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in results_iter
698. for rows in self.execute_sql(MULTI):
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in execute_sql
773. sql, params = self.as_sql()
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in as_sql
101. ordering, o_params, ordering_group_by = self.get_ordering()
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in get_ordering
428. self.query.get_meta(), default_order=asc):
File "/home/ic/test/bug2/lib/python2.7/site-
packages/django/db/models/sql/compiler.py" in find_ordering_name
468. if field.rel and path and opts.ordering:
Exception Type: AttributeError at /orders/
Exception Value: 'ManyToOneRel' object has no attribute 'rel'
}}}
In the view I'm ordering by the "price" field *which is not* in the
Article class. For some reason this triggered no errors with Django 1.6
and earlier, only 1.7 complains.
Removing the 'orders' app from the INSTALLED_APPS list, gets rid of the
error. I figured because it wasn't being used, but it appears Django 1.7
finds the apps anyway?
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:3>
* version: 1.7-beta-1 => 1.7-beta-2
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:4>
Comment (by shai):
I think you're getting an ordering on the reverse relation (that is, with
the reduced app, ordering Article instances by the id's of related Price
instances). You probably intended `order_by('price__price')` (if that
works, and the original doesn't, this should probably be a release-blocker
bug).
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:5>
Comment (by takis):
I can confirm that replacing order_by('price') by order_by('price_
_price') as you stated, makes the exception disappear. I'm having a closer
look at what's happening.
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:6>
Comment (by takis):
I just compared the behaviors:
Django 1.6.4
{{{
objs = Article.objects.all()
SELECT "orders_article"."id", "orders_article"."code",
"orders_article"."description"
FROM "orders_article"
pk 1 code A price 2
pk 2 code B price 1
objs = Article.objects.all().order_by('price')
SELECT "orders_article"."id", "orders_article"."code",
"orders_article"."description"
FROM "orders_article"
LEFT OUTER JOIN "orders_price" ON ( "orders_article"."id" =
"orders_price"."article_id" )
ORDER BY "orders_price"."id" ASC
pk 1 code A price 2
pk 2 code B price 1
objs = Article.objects.all().order_by('price_ _price'):
SELECT "orders_article"."id", "orders_article"."code",
"orders_article"."description"
FROM "orders_article"
LEFT OUTER JOIN "orders_price" ON ( "orders_article"."id" =
"orders_price"."article_id" )
ORDER BY "orders_price"."price" ASC
pk 2 code B price 1
pk 1 code A price 2
}}}
Django 1.7b3
{{{
objs = Article.objects.all()
SELECT "orders_article"."id", "orders_article"."code",
"orders_article"."description"
FROM "orders_article"
pk 1 code A price 2
pk 2 code B price 1
objs = Article.objects.all().order_by('price'):
'ManyToOneRel' object has no attribute 'rel'
objs = Article.objects.all().order_by('price_ _price'):
SELECT "orders_article"."id", "orders_article"."code",
"orders_article"."description"
FROM "orders_article"
LEFT OUTER JOIN "orders_price" ON ( "orders_article"."id" =
"orders_price"."article_id" )
ORDER BY "orders_price"."price" ASC
pk 2 code B price 1
pk 1 code A price 2
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:7>
* status: closed => new
* resolution: needsinfo =>
* component: Uncategorized => Database layer (models, ORM)
* severity: Normal => Release blocker
* stage: Unreviewed => Accepted
Comment:
Bisected to 20bab2cf9d02a5c6477d8aac066a635986e0d3f3. Attaching a
regression test.
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:8>
Old description:
New description:
--
Comment (by charettes):
I guess a simple `getattr(field, 'rel', None)` should fix this?
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:9>
Comment (by shai):
Replying to [comment:9 charettes]:
> I guess a simple `getattr(field, 'rel', None)` should fix this?
No, we need to fix it so that the field does have a `rel` attribute. This
is exactly like #19195, from the other side of the relation.
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:10>
Comment (by loic84):
How does ordering by the reverse of a FK even work considering there are
potentially many result?
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:11>
* owner: nobody => akaariai
* status: new => assigned
Comment:
Ordering by reverse FK is something that is possible even if it usually
doesn't make any sense. The interpretation is that one gets duplicate
results.
I'll assign this to myself.
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:12>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"76979a257d289b99998c463023308c888662d874"]:
{{{
#!CommitTicketReference repository=""
revision="76979a257d289b99998c463023308c888662d874"
[1.7.x] Fixed #22466 -- ordering by reverse foreign key
Ordering by reverse foreign key was broken by custom lookups patch
(commit 20bab2cf9d02a5c6477d8aac066a635986e0d3f3).
Thanks to everybody who helped solving this issue. Special thanks to
Trac alias takis for reporting this.
Backport of 3b7c66a3ac from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22466#comment:13>