Opened 11 years ago
Closed 11 years ago
#22466 closed Bug (fixed)
'ManyToOneRel' object has no attribute 'rel'
Reported by: | Takis Issaris | Owned by: | Anssi Kääriäinen |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.7-beta-2 |
Severity: | Release blocker | 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 )
I just installed Django 1.7b1 in my development virtualenv where I normally use Django 1.6.1. After fixing several expected things (mimetype, ugettext), I got an error which I could not find a reference to in the release notes:
AttributeError at /orders/price/ 'ManyToOneRel' object has no attribute 'rel'
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'
Attachments (1)
Change History (14)
comment:1 by , 11 years ago
Resolution: | → needsinfo |
---|---|
Status: | new → closed |
comment:2 by , 11 years ago
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.
comment:3 by , 11 years ago
Hi,
I finally found the time to minimize the application code, and track down the problem.
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)
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("")
from django.conf.urls import patterns, url urlpatterns = patterns('', url(r'^orders/', 'orders.views.testbug'), )
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?
comment:4 by , 11 years ago
Version: | 1.7-beta-1 → 1.7-beta-2 |
---|
comment:5 by , 11 years ago
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).
comment:6 by , 11 years ago
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.
comment:7 by , 11 years ago
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
comment:8 by , 11 years ago
Component: | Uncategorized → Database layer (models, ORM) |
---|---|
Resolution: | needsinfo |
Severity: | Normal → Release blocker |
Status: | closed → new |
Triage Stage: | Unreviewed → Accepted |
Bisected to 20bab2cf9d02a5c6477d8aac066a635986e0d3f3. Attaching a regression test.
by , 11 years ago
Attachment: | test22466.diff added |
---|
follow-up: 10 comment:9 by , 11 years ago
Description: | modified (diff) |
---|
I guess a simple getattr(field, 'rel', None)
should fix this?
comment:10 by , 11 years ago
comment:11 by , 11 years ago
How does ordering by the reverse of a FK even work considering there are potentially many result?
comment:12 by , 11 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
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.
comment:13 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
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!