#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:

> 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)

New description:

 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) 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 <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/065.009bdfdda93b6213827c231b7d7e0eb6%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to