Opened 2 years ago

Closed 2 years ago

Last modified 10 months ago

#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: master
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



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 Changed 2 years ago by Tim Graham

Resolution: wontfix
Status: newclosed
Summary: only()/defer() vs select_related()Allow select_related() to fetch individual fields from a related model

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 what only() is for). You could raise a discussion on the DevelopersMailingList to see if consensus emerges about a more elegant solution.

comment:3 Changed 10 months ago by Lev Lybin

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__{}' for x in g._meta.fields if not in {'r', 't', 's', 'u'}})

Last edited 10 months ago by Lev Lybin (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top