Opened 9 years ago
Closed 9 years ago
#26797 closed Bug (duplicate)
Reverse `related_name` of a proxy not accessible to inherited proxies in queryset
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 (last modified by )
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)
Attachments (1)
Change History (4)
by , 9 years ago
Attachment: | traceback.txt added |
---|
comment:1 by , 9 years ago
Description: | modified (diff) |
---|---|
Summary: | Reverse `related_name` of a proxy not accessible to inherited proxies → Reverse `related_name` of a proxy not accessible to inherited proxies in queryset |
comment:3 by , 9 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
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 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.
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:
Is this ticket still relevant? It is referenced in the 1.10 release notes:
I don't know if any backport is possible (looks like a new feature than a bug the way this note is written)