#32704: QuerySet.defer() doesn't clear deferred field when chaining with only().
-------------------------------------+-------------------------------------
     Reporter:  Manuel Baclet        |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  3.1
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  defer only           |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

 * stage:  Unreviewed => Accepted


Comment:

 Replying to [ticket:32704 Manuel Baclet]:
 > Considering a simple `Company` model with four fields: `id`, `name`,
 `trade_number` and `country`. If we evaluate a queryset containing a
 `.defer()` following a `.only()`, the generated sql query selects
 unexpected fields. For example:
 >
 > {{{#!python
 > Company.objects.only("name").defer("name")
 > }}}
 > loads all the fields with the following query:
 > {{{#!sql
 > SELECT "company"."id", "company"."name", "company"."trade_number",
 "company"."country" FROM "company"
 > }}}

 This is an expected behavior, `defer()` removes fields from the list of
 fields specified by the `only()` method (i.e. list of fields that should
 not be deferred). In this example `only()` adds `name` to the list,
 `defer()` removes `name` from the list, so you have empty lists and all
 fields will be loaded. It is also
 
[https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.only
 documented]:

 {{{
 # Final result is that everything except "headline" is deferred.
 Entry.objects.only("headline", "body").defer("body")
 }}}

 > {{{#!python
 > Company.objects.only("name").defer("name").defer("country")
 > }}}
 > also loads all the fields with the same query:
 > {{{#!sql
 > SELECT "company"."id", "company"."name", "company"."trade_number",
 "company"."country" FROM "company"
 > }}}

 I agree you shouldn't get all field, but only `pk`, `name`, and
 `trade_number`:
 {{{
 SELECT "ticket_32704_company"."id", "ticket_32704_company"."name",
 "ticket_32704_company"."trade_number" FROM "ticket_32704_company"
 }}}
 this is due to the fact that `defer()` doesn't clear the list of deferred
 field when chaining with `only()`. I attached a proposed patch.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32704#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/064.fc6c04e8e93718d4acc4fa281b7ddde2%40djangoproject.com.

Reply via email to