[Django] #26797: Reverse `related_name` of a proxy not accessible to inherited proxies

69 views
Skip to first unread message

Django

unread,
Jun 23, 2016, 5:54:31 AM6/23/16
to django-...@googlegroups.com
#26797: Reverse `related_name` of a proxy not accessible to inherited proxies
-------------------------------------+-------------------------------------
Reporter: mlorant | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) | Keywords: related_name reverse
Severity: Normal | relation
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Taken the following example (not real world use case, but it is somewhat
equivalent of something I encountered):

{{{
from django.db import models


class Animal(models.Model):
name = models.CharField("animal name", max_length=255, blank=True,
null=False)

class Mammal(Animal):
class Meta:
proxy = True

class Cat(Mammal):
class Meta:
proxy = True

class Dog(Mammal):
class Meta:
proxy = True

class TrueFriendship(models.Model):
mammal = models.ForeignKey(Mammal, related_name="dog_friends")
dog = models.ForeignKey(Dog, related_name="mammal_friends")
}}}

I want to get the number of friends of a queryset of cats. However, doing
this in a shell results in an exception:


{{{
>>> from nature.models import *
>>> cat = Cat.objects.create(name="cat1")
>>> dog = Dog.objects.create(name="dog1")
>>> TrueFriendship.objects.create(cat=cat, dog=dog)
>>> Cat.objects.annotate(nb_dog_friends=models.Count('dog_friends'))
Traceback (most recent call last):
File "/data/.virtualenvs/bugproxy/local/lib/python2.7/site-
packages/django/db/models/manager.py", line 122, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
[...]
File "/data/.virtualenvs/bugproxy/local/lib/python2.7/site-
packages/django/db/models/sql/query.py", line 1330, in names_to_path
"Choices are: %s" % (name, ", ".join(available)))
FieldError: Cannot resolve keyword 'dog_friends' into field. Choices are:
id, name
}}}

(Full traceback attached in a file) However, the same query using the
`Mammal` proxy works and the reverse relation is available on single
object:

{{{
>>>
Mammal.objects.annotate(nb_dog_friends=models.Count('dog_friends')).first().nb_dog_friends
1
>>> Cat.objects.first().dog_friends.all()
[<TrueFriendship: TrueFriendship object>]
}}}

Something is inconsistent here: I would expect to have access to
`dog_friends` in both cases (on a model instance and a queryset)

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

Django

unread,
Jun 23, 2016, 5:54:39 AM6/23/16
to django-...@googlegroups.com
#26797: Reverse `related_name` of a proxy not accessible to inherited proxies
-------------------------------------------+----------------------------

Reporter: mlorant | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.9
Severity: Normal | Resolution:
Keywords: related_name reverse relation | Triage Stage: Unreviewed

Has patch: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------------+----------------------------
Changes (by mlorant):

* Attachment "traceback.txt" added.

Django

unread,
Jun 23, 2016, 6:00:39 AM6/23/16
to django-...@googlegroups.com
#26797: Reverse `related_name` of a proxy not accessible to inherited proxies in
queryset

-------------------------------------+-------------------------------------
Reporter: mlorant | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution:
Keywords: related_name | Triage Stage:
reverse relation | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by mlorant):

* needs_docs: => 0
* needs_better_patch: => 0
* needs_tests: => 0


Old description:

New description:

{{{
from django.db import models

(Full traceback attached in a file) The same goes for "simple" query such
as `Cat.objects.filter(dog_friends__isnull=False)`. However, using the
`Mammal` proxy, both queries work and the reverse relation is available on
single `Cat` object:

{{{
>>>
Mammal.objects.annotate(nb_dog_friends=models.Count('dog_friends')).first().nb_dog_friends
1
>>> Cat.objects.first().dog_friends.all()
[<TrueFriendship: TrueFriendship object>]
}}}

Something is inconsistent here: I would expect to have access to
`dog_friends` in both cases (on a model instance and a queryset)

--

--
Ticket URL: <https://code.djangoproject.com/ticket/26797#comment:1>

Django

unread,
Jun 23, 2016, 6:06:09 AM6/23/16
to django-...@googlegroups.com
#26797: Reverse `related_name` of a proxy not accessible to inherited proxies in
queryset

-------------------------------------+-------------------------------------
Reporter: mlorant | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution:
Keywords: related_name | Triage Stage:
reverse relation | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by mlorant):

The bug seems to be only on the 1.9 branch (tried with 1.9.1, 1.9.6 &
1.9.7) in fact. I tried using Django==1.10b1 and the query works as
expected:

{{{
>>> Cat.objects.filter(dog_friends__isnull=False)
<QuerySet [<Cat: Cat object>]>
}}}

Is this ticket still relevant?

--
Ticket URL: <https://code.djangoproject.com/ticket/26797#comment:2>

Django

unread,
Jun 23, 2016, 9:49:47 AM6/23/16
to django-...@googlegroups.com
#26797: Reverse `related_name` of a proxy not accessible to inherited proxies in
queryset

-------------------------------------+-------------------------------------
Reporter: mlorant | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution: duplicate

Keywords: related_name | Triage Stage:
reverse relation | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by charettes):

* status: new => closed
* resolution: => duplicate


Comment:

Hi Maxime,

Thanks for your report.

As you've noticed this is a duplicate of #18012 which won't be backported
to 1.9 as it's not related to a security issue, a regression from 1.7, or
a bug in a new feature introduced in 1.8. You can have a look at our
[https://docs.djangoproject.com/en/1.9/internals/release-process
/#backwards-compatibility-policy backward compatibility policy] for more
details.

The release note was added under the ''Backwards incompatible changes in
1.10'' instead of the ''What’s new in Django 1.10'' where new feature are
documented which makes it clear to me it's not a new feature but if you
think the phrasing is inadequate please reopen with a suggested
alternative.

--
Ticket URL: <https://code.djangoproject.com/ticket/26797#comment:3>

Reply all
Reply to author
Forward
0 new messages