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