Opened 8 years ago
Last modified 8 years ago
#26797 closed Bug
Reverse `related_name` of a proxy not accessible to inherited proxies — at Initial Version
Reported by: | Maxime Lorant | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.9 |
Severity: | Normal | Keywords: | related_name reverse relation |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
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)