Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#33841 closed Uncategorized (worksforme)

Django shouldn't fail (bulk-)update silently when QuerySet is already evaluated.

Reported by: Shibel Karmi Mansour Owned by: nobody
Component: Database layer (models, ORM) Version: 3.2
Severity: Normal Keywords: update, bulk-update, queryset
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The following code:

initial_queryset = MyObject.objects.filter(...)
filtered_queryset = initial_queryset.exclude(related_model__id__in=...)
for_loop_on_filtered = [MyOtherModel(some_id=..., other_id=...) for x in
                          filtered_queryset]
MyOtherModel.objects.bulk_create(for_loop_on_filtered)
filtered_queryset.update(processed=True) # silent failure to update

Fails to update all objects in filtered_queryset. It seems like the reason is the list-comprehension on filtered_queryset.
I've been with Django for >6 years and this is by far the most surprising behavior I've seen.

It does seem to be documented (?):

"You cannot call update() on a QuerySet that has had a slice taken or can otherwise no longer be filtered."

But the fact is I can and did call update() on that QuerySet, and Django returned 0 errors.

If that is the intended behavior, then I suggest updating the documentation.

Change History (4)

comment:1 by Mariusz Felisiak, 2 years ago

Resolution: worksforme
Status: newclosed

Thanks for the report, however it works for me. Maybe in initial_queryset you filter out conditions that don't match any rows after adding MyOtherModel instances, it's hard to tell. Please use one of support channels to debug your issue.

comment:2 by Mariusz Felisiak, 2 years ago

Summary: Django shouldn't fail (bulk-)update silently when QuerySet is already evaluated / update documentationDjango shouldn't fail (bulk-)update silently when QuerySet is already evaluated.

comment:3 by Shibel Karmi Mansour, 2 years ago

I appreciate you taking the time to look into this, I don't think it should've been closed.

Maybe in initial_queryset you filter out conditions that don't match any rows after adding MyOtherModel instances, it's hard to tell.

That is not the case, and why would adding some OtherModel instances through iteration affect the results on MyObject models?

The code I put up above does not omit any ORM-level action, I've stopped the debugger one line before the update() call and the queryset size is > 0, only after I call the update() the queryset size becomes 0 (I'm not doing ANY filtering when doing the update() call, so that seems non-sensical).

Edit: I actually get the latest part. In my code, I'm selecting all elements where processed=False and updating them to processed=True. So I guess there's a filter operation there that leaves no such rows. I still don't see why the update fails. But I guess I'll have to debug this further.

Last edited 2 years ago by Shibel Karmi Mansour (previous) (diff)

comment:4 by Mariusz Felisiak, 2 years ago

I appreciate you taking the time to look into this, I don't think it should've been closed.

I cannot reproduce your issue, that's why it's closed. I don't think you've explained the issue in enough detail to confirm a bug in Django. Please reopen the ticket if you can debug your issue and provide details about why and where Django is at fault.

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