Realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals (which are a consequence of calling Model.save()). If you want to update a bunch of records for a model that has a custom save() method, loop over them and call save()
$. / manage.py shell
Python 2.7 .6(
default, Mar 22 2014, 22: 59: 38)[GCC 4.8 .2] on linux2
Type "help", "copyright", "credits"
or "license"
for more information.
(InteractiveConsole) >>>
from django.contrib.auth.models
import User
>>>
for u in User.objects.all():
...u.is_active = True
...u.save()
...
>>>
Fixed #23646 -- Added QuerySet.bulk_update() to efficiently update many models. , Update django-bulk-upate (https://github.com/aykut/django-bulk-update) which could/should be integrated into django core since we have a bulk_create and this corresponds well with the save (could be called bulk save if it makes sense). App works with an identical api to bulk_create and so should be a good candidate to be considered for inclusion in core. , Also, there is an app called django-bulk-upate (https://github.com/aykut/django-bulk-update) which could/should be integrated into django core since we have a bulk_create and this corresponds well with the save (could be called bulk save if it makes sense). App works with an identical api to bulk_create and so should be a good candidate to be considered for inclusion in core. , 1) Bulk-insert the new records into a temporary table 2) update in one statement using a join (SQL Server lets you do that) On hundreds of records, this was significantly faster than updating one-by-one (I no longer have access to any hard data, and it's irrelevant anyways).
Example:
Currently:
Books.objects.all().update(price = 10)
Proposed (syntax can vary):
Books.objects.all().update({
'pk': 1,
'price': 10
}, {
'pk': 2,
'price': 25
}])
The link you've provided suggests that the ORM example you've provided would be interpreted as:
UPDATE books_book SET price = 10 where pk = 1, price = 25 where pk = 2
So... what in the ORM statement identifies which column is to be used in the WHERE
clause, and which is to be updated? As currently expressed, it's ambiguous. You'd need to modify the statement to be something like:
Books.objects.all().update('pk', values = {
'pk': 1,
'price': 10
}, {
'pk': 2,
'price': 25
})
However, even with those changes, I'm not sure I see why doing this as a single statement version would be preferable to:
Book.objects.filter(pk = 1).update(price = 10) Book.objects.filter(pk = 2).update(price = 25)
UPDATE table, ( SELECT 1 id, 2 first, 3 second UNION ALL SELECT 2, 3, 4 UNION ALL... ) AS table_update SET table.first = table_update.first, table.second = table_update.second WHERE table.id IN(...) AND table.id = table_update.id
Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.,Returns a new QuerySet containing objects that match the given lookup parameters.,Returns a new QuerySet containing objects that do not match the given lookup parameters.,Returns an integer representing the number of objects in the database matching the QuerySet.
for e in Entry.objects.all():
print(e.headline)
async
for e in Entry.objects.all():
results.append(e)
entry_list = list(Entry.objects.all())
if Entry.objects.filter(headline = "Test"):
print("There is at least one Entry with the headline Test")
>>> import pickle >>> query = pickle.loads(s) # Assuming 's' is the pickled string. >>> qs = MyModel.objects.all() >>> qs.query = query # Restore the original 'query'.
>>> import pickle
>>> qs = Blog.objects.values_list('id', 'name')
>>> qs
<QuerySet [(1, 'Beatles Blog')]>
>>> reloaded_qs = Blog.objects.all()
>>> reloaded_qs.query = pickle.loads(pickle.dumps(qs.query))
>>> reloaded_qs
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
Then you will need to import transaction wherever your above function resides;,Now when that function is called it will only have one transaction, rather then N. If it fails, the transaction rollsback.,I think what you mean is one transaction in the transaction manager, rather than one transaction per iteration.,https://docs.djangoproject.com/en/dev/topics/db/transactions/
You will need to add this line to your middleware_classes in settings.py
'django.middleware.transaction.TransactionMiddleware',
Then you will need to import transaction wherever your above function resides;
from django.db
import transaction
Put your loop in a function and add a decorator, like so:
@transaction.commit_on_success
def my_function():
i = 1
for p in Photo.objects.order_by("-current_rating"):
p.current_rank = i
p.save()
i += 1
django-simple-history functions by saving history using a post_save signal every time that an object with history is saved. However, for certain bulk operations, such as bulk_create, bulk_update, and queryset updates, signals are not sent, and the history is not saved automatically. However, django-simple-history provides utility functions to work around this.,As of django-simple-history 2.2.0, we can use the utility function bulk_create_with_history in order to bulk create objects while saving their history:,django-simple-history supports tracking history on models that use multi-table inheritance, such as:,Unlike with bulk_create, queryset updates perform an SQL update query on the queryset, and never return the actual updated objects (which would be necessary for the inserts into the historical table). Thus, we tell you that queryset updates will not save history (since no post_save signal is sent). As the Django documentation says:
>>> from simple_history.utils
import bulk_create_with_history
>>>
from simple_history.tests.models
import Poll
>>>
from django.utils.timezone
import now
>>>
>>>
data = [Poll(id = x, question = 'Question ' + str(x), pub_date = now()) for x in range(1000)] >>>
objs = bulk_create_with_history(data, Poll, batch_size = 500) >>>
Poll.objects.count()
1000
>>>
Poll.history.count()
1000
>>>
for poll in data:
poll._change_reason = 'reason'
poll._history_user = my_user
poll._history_date = some_date >>>
objs = bulk_create_with_history(data, Poll, batch_size = 500) >>>
Poll.history.get(id = data[0].id).history_change_reason 'reason'
>>> user = User.objects.create_user("tester", "tester@example.com") >>>
objs = bulk_create_with_history(data, Poll, batch_size = 500, default_user = user) >>>
Poll.history.get(id = data[0].id).history_user == user
True
>>> from simple_history.utils
import bulk_update_with_history
>>>
from simple_history.tests.models
import Poll
>>>
from django.utils.timezone
import now
>>>
>>>
data = [Poll(id = x, question = 'Question ' + str(x), pub_date = now()) for x in range(1000)] >>>
objs = bulk_create_with_history(data, Poll, batch_size = 500) >>>
for obj in objs: obj.question = 'Duplicate Questions' >>>
bulk_update_with_history(objs, Poll, ['question'], batch_size = 500) >>>
Poll.objects.first().question 'Duplicate Question``
>>> from simple_history.utils
import bulk_update_with_history
>>>
from simple_history.tests.models
import PollWithAlternativeManager
>>>
>>>
data = [PollWithAlternativeManager(id = x, question = 'Question ' + str(x), pub_date = now()) for x in range(1000)] >>>
objs = bulk_create_with_history(data, PollWithAlternativeManager, batch_size = 500, manager = PollWithAlternativeManager.all_polls)
If you want to update a bunch of records
for a model that has a custom
``
save()``
method, loop over them and call ``
save()``, like this: