Opened 11 years ago

Closed 8 years ago

#19531 closed Cleanup/optimization (fixed)

Surprising impact of defer()

Reported by: Vlada Macek Owned by: nobody
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords: defer only
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have Counter model with a few fields. When I call:

>>> cnt=Counter.objects.only('logs').get(id=2349497)

it results in SQL (Postgres):

SELECT "visits_counter"."id", "visits_counter"."logs" FROM "visits_counter" WHERE "visits_counter"."id" = 2349497

That's fine. When I want to directly update the logs field in the database like this:

cnt._default_manager.filter(pk=cnt.pk).update(logs=4)

it results in SQL (Postgres):

SELECT U0."id" FROM "visits_counter" U0 WHERE U0."id" = 2349497
UPDATE "visits_counter" SET "logs" = 4 WHERE "visits_counter"."id" IN (2349497)

which looks strange to me (1. the unnecessary first query, 2. IN in the second). I finally get expected behavior by doing

cnt._meta.concrete_model._default_manager.filter(pk=cnt.pk).update(logs=4)

SQL:

UPDATE "visits_counter" SET "logs" = 4 WHERE "visits_counter"."id" = 2349497

Is it a bug or feature? Am I getting something really wrong?

Change History (2)

comment:1 by Anssi Kääriäinen, 11 years ago

Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization

In 1.5 you could use cnt = Counter.objects.only('logs').get(id=2349497); cnt.logs=4; cnt.save() - 1.5 will automatically update only those fields loaded (or modified since load).

As for the SELECT in the second clause - I think this is because Django mixes proxy and "real" inheritance in the update code. But this isn't necessary, using the concrete_model and the proxied model should work equivalently in this case. And, the reason for the proxy model is the internal implementation of deferred loading.

I haven't verified the behavior in master, still marking accepted on the basis of proxy <-> concrete model .update() behavior difference.

comment:2 by Simon Charette, 8 years ago

Resolution: fixed
Status: newclosed

It looks like this effectively fixed by 99321e30cebbffeafc6ae19f4f92a0a665cbf19b (#18306) as the added tests demonstrate.

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