#29072 closed New feature (wontfix)
Allow select_related() to fetch individual fields from a related model
Reported by: | Дилян Палаузов | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Provided
class M(models.Model): n = models.IntegerField() r = models.IntegerField() t = models.IntegerField() s = models.IntegerField() u = models.IntegerField() class F(models.Model): g = models.ForeignKey(M, on_delete=models.CASCADE) a = models.IntegerField() b = models.IntegerField() c = models.IntegerField() d = models.IntegerField() e = models.IntegerField()
I want to obtain with a queryset all fields from F and M.n, but not the other fields of M like M.r. This works F.objects.select_related('g').defer('g__r', 'g__t', 'g__s', 'g__u')
but I don't like it, as I want to say only M.n has to be obtained, and not the others. prefetch_related is also suboptimal, as it creates two SQL queries instead of one. only()
does not let me specify 'All fields of F'.
F.objects.select_related('g__n')
would fit from logic, but does not work (django.core.exceptions.FieldError: Non-relational field given in select_related: 'n'. Choices are: (none)
)
Please make select_related()
accept the above expression.
This applies to both master and 1.11.
Change History (3)
comment:1 by , 7 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Summary: | only()/defer() vs select_related() → Allow select_related() to fetch individual fields from a related model |
comment:3 by , 5 years ago
I was looking for how to more elegant reduce joined query what author talk, and not found good solution, list all unneeded fields of joined table in 'defer' is not elegant solution. At this moment django doesn't has it. If look on how can customize prefetch_related with Prefetch() I have suggestion create e.g. 'Select' for select_related and use it like that: select_related('g') or select_related(Select('g').only('r', 't', 's', 'u'))
My current solution:
select_related('g').defer(*{f'g__{x.name}' for x in g._meta.fields if x.name not in {'r', 't', 's', 'u'}})
I'm not in love with the proposed API. Giving
select _related()
the ability to fetch individual fields doesn't seem like a proper separation of concerns (that's whatonly()
is for). You could raise a discussion on the DevelopersMailingList to see if consensus emerges about a more elegant solution.