Code

Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#15962 closed Bug (invalid)

RelatedField.related_query_name() returns the wrong name if the default related_name has not been overridden

Reported by: bmispelon Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX:

Description

As an example, using the following models:

class Author(models.Model):
    pass


class Book(models.Model):
    author = models.ForeignKey(Author)

Doing Author._meta.get_field_by_name('book_set') throws a FieldDoesNotExists error.

To get the field, you currently have to do get_field_by_name('book').

The attached patch corrects the related_query_name method of django.db.models.fields.RelatedField to use the same logic as django.db.models.RelatedObject.get_accessor_name().

Attachments (1)

15962.diff (698 bytes) - added by bmispelon 3 years ago.

Download all attachments as: .zip

Change History (5)

Changed 3 years ago by bmispelon

comment:1 follow-up: Changed 3 years ago by lukeplant

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

Using exactly your models, this works for me:

>>> models.Author._meta.get_field_by_name('book_set')                        
(<RelatedObject: ticket15962:book related to author>, None, False, False)

Also, note that the related_query_name is the name used in queries. The get_accessor_name is the attribute on objects that is used to return the QuerySet of related objects. These are not necessarily the same (especially for ManyToMany fields), and they should not be changed to make them the same as each other. (Huge number of test suite failures result if you do).

comment:2 in reply to: ↑ 1 Changed 3 years ago by bmispelon

I'm not sure what I'm doing wrong then but on a fresh install of trunk, I still get the error:

>>> Author._meta.get_field_by_name('book_set') 
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/me/.virtualenvs/bug15962/src/django/django/db/models/options.py", line 306, in get_field_by_name
    % (self.object_name, name))
FieldDoesNotExist: Author has no field named 'book_set'

But what you say about related_query_name and get_accessor_name beeing different makes sense.
I ran the test suite with my patch and I get some failures indeed (though only 5): it seems to break things like Permission.objects.filter(group__user=user_obj) for contrib.auth.

What confused me was the fact that if the field's related_name is set, then both methods return it and I therefore assumed they should also return the same value when related_name was not set.

comment:3 follow-up: Changed 3 years ago by lukeplant

Oops, look like I confused myself messing around with your patch or some stale .pyc files or something, because I'm getting that failure now.

Although this is a kind of inconsistency that would be nice to change, it's not a bug, and not something we can change without very big backwards incompatibility problems. So I'm leaving it as closed.

comment:4 in reply to: ↑ 3 Changed 3 years ago by bmispelon

I understand.

Thanks for taking the time to explain.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.