Opened 9 years ago
Last modified 9 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)