Django

Code

Ticket #7298 (closed: fixed)

Opened 2 years ago

Last modified 2 years ago

update() on a sliced query set updates all objects.

Reported by: sebastian_noack Assigned to: nobody
Milestone: Component: Database layer (models, ORM)
Version: SVN Keywords: qsrf-cleanup
Cc: russellm, mtredinnick Triage Stage: Unreviewed
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

What do think following code will do?

model.objects.all()[:1].update(foo='bar')

No it won't update the first object in the model, it will update all objects. Although I expected that it updates the first object, we should just prevent the user from doing this. Because of (at least MySql?) do not support offset for UPDATE. It supports limit but their might be DBMS which do not support both on UPDATE and if you think about this use case, it is a real corner case. But anyway the user should not destroy his data by accident. I have written a patch which adds the same sanity check to QuerySet?.update() as already done when calling QuerySet?.order_by().

Attachments

0001-Preventing-update-on-a-sliced-QuerySet-7298.patch (1.5 kB) - added by sebastian_noack on 05/23/08 10:11:53.
prevent_update_queryset_r7599.patch (1.5 kB) - added by gav on 06/09/08 00:00:39.
Prevents updates on querysets, patched against r7599

Change History

05/23/08 10:11:53 changed by sebastian_noack

  • attachment 0001-Preventing-update-on-a-sliced-QuerySet-7298.patch added.

06/08/08 23:59:48 changed by gav

  • keywords set to qsrf-cleanup.
  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

I think this patch is the right approach, I've only expanded it slightly by adding it in to the other update-like method on querysets, and cleaned up the wording a bit.

06/09/08 00:00:39 changed by gav

  • attachment prevent_update_queryset_r7599.patch added.

Prevents updates on querysets, patched against r7599

06/09/08 11:17:54 changed by jacob

  • status changed from new to closed.
  • resolution set to fixed.

(In [7601]) Fixed #7298: prevent update() on sliced QuerySet? since UPDATE doesn't reliably support LIMIT/OFFSET. Thanks, George Vilches.

06/09/08 13:22:39 changed by emulbreh

QuerySet?.update() bypasses custom Model.save() methods. If this is intended behaviour the docs should mention it. Otherwise there had to be code to iterate the queryset anyway (manually updating each object) that could be applied to sliced querysets as well.

06/10/08 04:44:49 changed by sebastian_noack

Not only overriden save() methods are bypassed, also the pre_save() method of fields are ignored. But at first, this has nothing to do with this ticket. And at second, the update() method is not a shortcut for, following:

for obj in query_set:
    obj.foo = 'bar'
    obj.save()

The update() method is intended to be a low level API to the UPDATE sql statement, to enable updating multiple objects at once with a single query. Maybe the documentation should explain this more clearly, if required.

06/23/08 08:07:38 changed by emulbreh

Mhm. I thought this was symmetrical to #6915, which jacob seemed to agree should be fixed. I opened #7447 as I had not seen your comment yet. At least there should be a warning in the docs: "If you want to write reusable code, you better not use QuerySet?.update()."


Add/Change #7298 (update() on a sliced query set updates all objects.)




Change Properties
Action