Opened 7 months ago

Last modified 6 months ago

#29260 new Bug

Remove UPDATE query when saving a new model instance with a primary key that has a default

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

Description (last modified by user0007)

Using a model's instance:

class Account(models.Model):
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    title = models.TextField()

>> account = Account()
>> account.title = "abc"
>> account.save()

1. UPDATE "app_account" SET "title" = \'\', WHERE "app_account"."id" = \'67c9327d-150e-419f-b493-0c2c59a045c3\'::uuid',
2. INSERT INTO "app_account" ("title", "id") VALUES (\'abc\', \'3d8c1b3c-214a-4798-a0fa-d4c22c2b877f\'::uuid)

Using a model's manager method:

>> Account.objects.create(title="abc")

1. INSERT INTO "app_account" ("title", "id") VALUES (\'abc\', \'3d8c1b3c-214a-4798-a0fa-d4c22c2b877f\'::uuid)

Using a model's instance with force_insert argument:

>> account = Account()
>> account.title = "abc"
>> account.save(force_insert=true)

1. INSERT INTO "app_account" ("title", "id") VALUES (\'abc\', \'3d8c1b3c-214a-4798-a0fa-d4c22c2b877f\'::uuid)

Related issue? https://code.djangoproject.com/ticket/29129

Change History (7)

comment:1 Changed 7 months ago by user0007

Description: modified (diff)

comment:2 Changed 7 months ago by Tim Graham

I'm not sure if the issue can or should be fixed. For the model you gave, an instance will have an id from default=uuid.uuid4, so as documented an UPDATE is tried (code). A fix might try to detect if the primary key came from a default and if so, skip the update.

comment:3 Changed 7 months ago by Simon Charette

A fix might try to detect if the primary key came from a default and if so, skip the update.

I think we could use some kind of self._state.adding and self._meta.pk.default heuristics to automatically set force_insert=True on the last table/leaf child. That would break the following scenario though.

a = Account(pk='known-uuid-pk')
a.title = new_title
a.save()  # expects an UPDATE here.

But I would argue that force_update should be passed in this case.

That wouldn't solve the MTI issue described in #29129 but that would do for this case.

comment:4 Changed 7 months ago by Tim Graham

Summary: Django makes an extra UPDATE query when custom PK is evaluating before save.Remove UPDATE query when saving a new model instance with a primar key that has a default
Triage Stage: UnreviewedAccepted

comment:5 Changed 7 months ago by Tim Graham

Summary: Remove UPDATE query when saving a new model instance with a primar key that has a defaultRemove UPDATE query when saving a new model instance with a primary key that has a default

comment:6 Changed 6 months ago by Windson yang

@Tim Graham, should we still work on it?

comment:7 Changed 6 months ago by Tim Graham

Simon's proposal seems fine to me.

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