#26092: Regression when using order_by() on a ManyToManyField using the 
'through'
feature
-------------------------------------+-------------------------------------
     Reporter:  wjakob               |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  1.9
  (models, ORM)                      |
     Severity:  Release blocker      |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by timgraham):

 * stage:  Unreviewed => Accepted
 * severity:  Normal => Release blocker


Old description:

> Hi,
>
> I'm seeing a serious regression (AttributeError exception thrown) when
> using the order_by() feature on a ManyToManyField in combination with the
> 'through' feature.
>
> This worked perfectly fine in Django 1.8.x, I'm seeing it for the first
> time now. IMHO it is a release blocker, but then the release is already
> out (so I set the severity as 'Normal').
>
> See below for a minimal example:
>
> {{{#!python
> from django.db import models
>

> class Person(models.Model):
>     name = models.CharField(max_length=200)
>

> class Publication(models.Model):
>     title          = models.CharField(max_length=200)
>     authors        = models.ManyToManyField(Person, through='Author')
>
>     def get_authors(self):
>         return self.authors.order_by('author_to_publication')
>

> class Author(models.Model):
>     person      = models.ForeignKey(Person, verbose_name='Author',
>                                     related_name='author_to_publication')
>     publication = models.ForeignKey(Publication,
> verbose_name='Publication')
>     order_id    = models.PositiveSmallIntegerField(default=0)
>
>     class Meta:
>         ordering = ['order_id']
> }}}
>
> And here is an example shell session which causes the problem
>
> {{{#!python
>  % ./manage.py shell
> [INS]
> Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 23 2015, 02:52:03)
> [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
> Type "help", "copyright", "credits" or "license" for more information.
> (InteractiveConsole)
> >>>
> >>> person = myapp.models.Person()
> >>> person.save()
> >>>
> >>> publication = myapp.models.Publication(title='test publication')
> >>> publication.save()
> >>> author = myapp.models.Author(person=person, publication=publication,
> order_id=1)
> >>> author.save()
> >>>
> >>> publication.authors.order_by('author_to_publication')
> Traceback (most recent call last):
>   File "<console>", line 1, in <module>
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/query.py", line 234, in __repr__
>     data = list(self[:REPR_OUTPUT_SIZE + 1])
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/query.py", line 258, in __iter__
>     self._fetch_all()
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/query.py", line 1074, in _fetch_all
>     self._result_cache = list(self.iterator())
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/query.py", line 52, in __iter__
>     results = compiler.execute_sql()
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/sql/compiler.py", line 837, in execute_sql
>     sql, params = self.as_sql()
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/sql/compiler.py", line 382, in as_sql
>     extra_select, order_by, group_by = self.pre_sql_setup()
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/sql/compiler.py", line 49, in pre_sql_setup
>     order_by = self.get_order_by()
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/sql/compiler.py", line 295, in get_order_by
>     field, self.query.get_meta(), default_order=asc))
>   File "/Users/wenzel/mysite/lib/python3.4/site-
> packages/django/db/models/sql/compiler.py", line 571, in
> find_ordering_name
>     if field.is_relation and path and opts.ordering and name !=
> field.attname:
> AttributeError: 'ManyToOneRel' object has no attribute 'attname'
> >>>
> }}}

New description:

 Hi,

 I'm seeing a serious regression (AttributeError exception thrown) when
 using the order_by() feature on a ManyToManyField in combination with the
 'through' feature.

 This worked perfectly fine in Django 1.8.x, I'm seeing it for the first
 time now. IMHO it is a release blocker, but then the release is already
 out (so I set the severity as 'Normal').

 See below for a minimal example:

 {{{#!python
 class Person(models.Model):
     name = models.CharField(max_length=200)


 class Publication(models.Model):
     title = models.CharField(max_length=200)
     authors = models.ManyToManyField(Person, through='Author')


 class Author(models.Model):
     person = models.ForeignKey(Person,
 related_name='author_to_publication')
     publication = models.ForeignKey(Publication)
     order_id = models.PositiveSmallIntegerField(default=0)

     class Meta:
         ordering = ['order_id']
 }}}

 And here is an example test which causes the problem:

 {{{#!python
 from django.test import TestCase

 from .models import Person, Publication, Author


 class Test(TestCase):
     def test(self):
         person = Person()
         person.save()
         publication = Publication(title='test publication')
         publication.save()
         author = Author(person=person, publication=publication,
 order_id=1)
         author.save()
         list(publication.authors.order_by('author_to_publication'))

 Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/query.py", line 234, in __repr__
     data = list(self[:REPR_OUTPUT_SIZE + 1])
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/query.py", line 258, in __iter__
     self._fetch_all()
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/query.py", line 1074, in _fetch_all
     self._result_cache = list(self.iterator())
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/query.py", line 52, in __iter__
     results = compiler.execute_sql()
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/sql/compiler.py", line 837, in execute_sql
     sql, params = self.as_sql()
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/sql/compiler.py", line 382, in as_sql
     extra_select, order_by, group_by = self.pre_sql_setup()
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/sql/compiler.py", line 49, in pre_sql_setup
     order_by = self.get_order_by()
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/sql/compiler.py", line 295, in get_order_by
     field, self.query.get_meta(), default_order=asc))
   File "/Users/wenzel/mysite/lib/python3.4/site-
 packages/django/db/models/sql/compiler.py", line 571, in
 find_ordering_name
     if field.is_relation and path and opts.ordering and name !=
 field.attname:
 AttributeError: 'ManyToOneRel' object has no attribute 'attname'
 }}}

--

Comment:

 Bisected to d43aa28f67c52bc6f5ea5868c711df263895713f

--
Ticket URL: <https://code.djangoproject.com/ticket/26092#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/064.1c7c5dc13584e5eee570e801d079786e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to