Opened 11 years ago

Last modified 11 years ago

#22466 closed Bug

'ManyToOneRel' object has no attribute 'rel' — at Version 9

Reported by: Takis Issaris Owned by: nobody
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 Simon Charette)

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'

Change History (10)

comment:1 by Baptiste Mispelon, 11 years ago

Resolution: needsinfo
Status: newclosed

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!

comment:2 by Takis Issaris, 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 Takis Issaris, 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 Takis Issaris, 11 years ago

Version: 1.7-beta-11.7-beta-2

comment:5 by Shai Berger, 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 Takis Issaris, 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 Takis Issaris, 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 Tim Graham, 11 years ago

Component: UncategorizedDatabase layer (models, ORM)
Resolution: needsinfo
Severity: NormalRelease blocker
Status: closednew
Triage Stage: UnreviewedAccepted

Bisected to 20bab2cf9d02a5c6477d8aac066a635986e0d3f3. Attaching a regression test.

by Tim Graham, 11 years ago

Attachment: test22466.diff added

comment:9 by Simon Charette, 11 years ago

Description: modified (diff)

I guess a simple getattr(field, 'rel', None) should fix this?

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