Make django's QuerySet.update().order_by('') work for MySQL
See original GitHub issueSummary: Since MySQL does not support a defered unique constraint (like some other databases do), it would be great if this package could supply a way to update with an order_by clause. More here. For example the
UPDATE t SET id = id + 1 ORDER BY id DESC;
example from the MySQL docs is currently not working with Django 2.2 and still gives an IntegrityError for the unique key.
The query that is executed is:
query = 'UPDATE `model` SET `integerfield` = (`model`.`integerfield` + %s) WHERE (`model`.`date` = %s AND `model`.`integerfield` >= %s)'
args = (1, '2020-04-26', 2)
As you can see the ORDER_BY, which should make it work, is omitted in the query, while it is in the Django code:
qs_to_increase = self.get_indexing_queryset().filter(
integerfield__gte=self.integerfield).order_by('-integerfield')
# apply changes after getting the qs!
qs_to_increase.update(integerfield=F('integerfield') + 1)
Django Version: Django 2.2
Database and version used: MySQL 8.0.20-0ubuntu0.19.10.1
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
How to select a record and update it, with a single queryset in ...
Use the queryset object update method: MyModel.objects.filter(pk=some_value).update(field1='some value').
Read more >#20708 (QuerySet.update() ignores order_by() clause) – Django
This is a problem with MySQL, because for bulk updates on a unique key, you must specify the working order, otherwise the above...
Read more >Django QuerySet - Order By - W3Schools
Order By. To sort QuerySets, Django uses the order_by() method: · Descending Order. By default, the result is sorted ascending (the lowest value...
Read more >Django Tutorial Part 3: Using models - Learn web development
The reverse() function above is able to "reverse" your URL mapper (in the above case named 'model-detail-view') in order to create a URL...
Read more >Filtering - Django REST framework
The root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Thanks for the ticket, I’ve CC’d myself and added a reply.
Your instrumentation looks about right. You don’t need the table name per se, and should use
+=
to actually mutate the local SQL variable:sql += ' ORDER BY column_name'
.I just wanted to follow up on this, since upgrading to Django 3.1 breaks this way of solving it.
It is because of this commit (I believe): https://github.com/django/django/commit/a19505eb2ecd4a07ff39f3f66898e68b69d0e680#diff-dabf20e4ab58ae26d868833eefa64d93896519623d676bdb47bee47b0b6b5543 Before performing the database execution a simple “SELECT VERSION()” is issued if the connection is newly initiated. If you apply the database instrumentation hook, it will fail for not finding the table.
Fixed it by applying a
before I change the sql.