#10913 closed Cleanup/optimization (fixed)
Document how related_name affects QuerySet filtering
Reported by: | neithere | Owned by: | Tim Graham |
---|---|---|---|
Component: | Documentation | Version: | dev |
Severity: | Normal | Keywords: | orm, related_name, |
Cc: | greg@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | yes |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The documentation states that by default the "backward" relationship Manager "is named FOO_set
, where FOO
is the source model name, lowercased". However, in the latest SVN snapshot the behaviour seems to be inconsistent.
models.py
from django.db import models class Author(models.Model): name = models.CharField(max_length=255) class Book(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey(Author) # by default, related_name='book_set'
The related_name
argument is commented out. If not, everything works fine, but let's see what happens now:
In shell after syncdb:
>>> from fooapp.models import Author, Book >>> Author.book_set <django.db.models.fields.related.ForeignRelatedObjectsDescriptor object at 0x27f4e90> >>> Author.book Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: type object 'Author' has no attribute 'book' >>> a=Author.objects.create(name='John') >>> b=Book.objects.create(title='My Book', author=a) >>> Author.objects.filter(book_set__exact=1) Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/local/lib/python2.6/dist-packages/Django-1.1_beta_1-py2.6.egg/django/db/models/manager.py", line 129, in filter return self.get_query_set().filter(*args, **kwargs) File "/usr/local/lib/python2.6/dist-packages/Django-1.1_beta_1-py2.6.egg/django/db/models/query.py", line 466, in filter return self._filter_or_exclude(False, *args, **kwargs) File "/usr/local/lib/python2.6/dist-packages/Django-1.1_beta_1-py2.6.egg/django/db/models/query.py", line 484, in _filter_or_exclude clone.query.add_q(Q(*args, **kwargs)) File "/usr/local/lib/python2.6/dist-packages/Django-1.1_beta_1-py2.6.egg/django/db/models/sql/query.py", line 1613, in add_q can_reuse=used_aliases) File "/usr/local/lib/python2.6/dist-packages/Django-1.1_beta_1-py2.6.egg/django/db/models/sql/query.py", line 1511, in add_filter negate=negate, process_extras=process_extras) File "/usr/local/lib/python2.6/dist-packages/Django-1.1_beta_1-py2.6.egg/django/db/models/sql/query.py", line 1676, in setup_joins "Choices are: %s" % (name, ", ".join(names))) FieldError: Cannot resolve keyword 'book_set' into field. Choices are: book, id, name >>> Author.objects.filter(book__exact=1) [<Author: John>]
Change History (11)
comment:1 by , 16 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 13 years ago
Cc: | added |
---|---|
Easy pickings: | unset |
Resolution: | invalid |
Severity: | → Normal |
Status: | closed → reopened |
Type: | → Uncategorized |
UI/UX: | unset |
I think the OP is correct here, at least in that the ORM is inconsistent. The docs state that the default related name is FOO_set
, and while this is true when accessing the manager, the OP gets differing behaviour when explicitly setting related_name='book_set'
to the default when filtering (as do I). To spell it out again, the following will work:
class Event(models.Model): ... class Image(models.Model): event = models.ForeignKey(Event, related_name='image_set') >>> Event.objects.filter(image_set__isnull=True)
Whereas this will throw a FieldError
:
class Event(models.Model): ... class Image(models.Model): event = models.ForeignKey(Event) >>> Event.objects.filter(image_set__isnull=True)
This ticket does not indicate "a misunderstanding about Django, how it works, and how to use it"; rather it points out a gotcha that needs to be fixed, or at the very least properly documented.
comment:2 by , 13 years ago
Cc: | added |
---|---|
Easy pickings: | unset |
Resolution: | invalid |
Severity: | → Normal |
Status: | closed → reopened |
Type: | → Uncategorized |
UI/UX: | unset |
I think the OP is correct here, at least in that the ORM is inconsistent. The docs state that the default related name is FOO_set
, and while this is true when accessing the manager, the OP gets differing behaviour when explicitly setting related_name='book_set'
to the default when filtering (as do I). To spell it out again, the following will work:
class Event(models.Model): ... class Image(models.Model): event = models.ForeignKey(Event, related_name='image_set') >>> Event.objects.filter(image_set__isnull=True)
Whereas this will throw a FieldError
:
class Event(models.Model): ... class Image(models.Model): event = models.ForeignKey(Event) >>> Event.objects.filter(image_set__isnull=True)
This ticket does not indicate "a misunderstanding about Django, how it works, and how to use it"; rather it points out a gotcha that needs to be fixed, or at the very least properly documented.
comment:2 by , 13 years ago
Easy pickings: | unset |
---|---|
Resolution: | invalid |
Severity: | → Normal |
Status: | closed → reopened |
Type: | → Uncategorized |
UI/UX: | unset |
I think the OP is correct here, at least in that the ORM is inconsistent. The docs state that the default related name is FOO_set
, and while this is true when accessing the manager, the OP gets differing behaviour when explicitly setting related_name='book_set'
to the default when filtering (as do I). To spell it out again, the following will work:
class Event(models.Model): ... class Image(models.Model): event = models.ForeignKey(Event, related_name='image_set') >>> Event.objects.filter(image_set__isnull=True)
Whereas this will throw a FieldError
:
class Event(models.Model): ... class Image(models.Model): event = models.ForeignKey(Event) >>> Event.objects.filter(image_set__isnull=True)
This ticket does not indicate "a misunderstanding about Django, how it works, and how to use it"; rather it points out a gotcha that needs to be fixed, or at the very least properly documented.
comment:3 by , 13 years ago
Sorry about that, I was getting gateway timeouts so hit refresh a couple of times.
comment:4 by , 13 years ago
Component: | Database layer (models, ORM) → Documentation |
---|---|
Needs documentation: | set |
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Cleanup/optimization |
The code example you provide is working as intended. However, I'll accept this ticket as a documentation issue; a quick scan of the related_name docs didn't reveal anything describing this behavior.
comment:6 by , 12 years ago
Status: | reopened → new |
---|
comment:7 by , 11 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Summary: | Default related_name is broken → Document how related_name affects QuerySet filtering |
comment:8 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Everything you show looks correct. book_set is not a field, it is a type of queryset Manager that you can use to access the set of books by a particular Author instance. Therefore, since it is not a field, you cannot filter on it. Rather, you filter on the actual field you are interested in. If you have additional questions, please post to django-users, not the ticket tracker. What you have posted here indicates a misunderstanding about Django, how it works, and how to use it, not a bug in Django. The django-users mailing list will be a better place to get misunderstandings cleared up than the ticket tracker.