Opened 2 months ago
Closed 2 months ago
#35780 closed Cleanup/optimization (duplicate)
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.
Thank you for the ticket Andrew
I feel that the underlying issue is the same as for #13871 and so marking as a duplicate