Opened 2 hours ago

#35780 new Cleanup/optimization

ForeignKey choices in admin have no option to avoid lazy evaluation of model attributes

Reported by: Andrew Udvare Owned by:
Component: Uncategorized Version: 5.1
Severity: Normal Keywords: admin
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

https://github.com/django/django/blob/main/django/db/models/fields/__init__.py#L1073

It would be great if after the above line a value passed in the field (such as ForeignKey) could be used to specify items to pass to select_related() or simply to call select_related(). Prefetch ability would also be good too.

In admin, there is an option for the listing list_select_related but no option to make queries for choices run with select/prefetch related. An option in ModelAdmin like choices_select_related = True would at least call select_related() with no arguments above. Or it could be at the field level with an option like choices_select_related=('user',) or accept True. A more complex type could also be used for handling specific fields (example with FriendInfo model with one-to-one with User): choices_select_related = {'best_friend': 'best_friend__user' }, an option for ModelAdmin.

Example case: If you are using a model keyed off User as recommended in the docs, then in the default case, if UserDetails.__str__ returns self.user.full_name, another query has to be executed. This means for every single user a new query has to be executed just to list them out. Plus there may be other fields that want to list users with different parameters. Total queries are then n_rel_fields * n_users + 1.

class UserDetails(models.Model):
    user = models.OneToOneField(User)

    def __str__(self):
        return f'{self.user.full_name}'

admin.site.register(UserDetails)

At admin/userdetails/:id every access of .user will need another query for every user. With an argument such as choices_select_related=True, .select_related() could be called on or after the line linked above.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top