Как "массовое обновление" с помощью Django?
Я хочу обновить таблицу Django - что-то вроде этого в raw SQL:
update tbl_name set name = 'foo' where name = 'bar'
Мой первый результат - это что-то вроде этого - но это противно, не так ли?
list = ModelClass.objects.filter(name = 'bar')
for obj in list:
obj.name = 'foo'
obj.save()
Есть ли более элегантный способ?
Ответы
Ответ 1
Версия UPD Django 2.2 теперь имеет объемную_датку.
Обратитесь к следующему разделу документации django
Обновление нескольких объектов одновременно
Короче говоря, вы должны быть в состоянии использовать:
ModelClass.objects.filter(name='bar').update(name="foo")
Вы также можете использовать объекты F
для таких вещей, как увеличение строк:
from django.db.models import F
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
См. Документацию: https://docs.djangoproject.com/en/1.9/topics/db/queries/.
Однако обратите внимание, что:
- Это не будет использовать метод
ModelClass.save
(поэтому, если у вас есть некоторая логика внутри, он не будет запущен). - Сигналы Django не будут излучаться.
Ответ 2
Рассмотрите возможность использования django-bulk-update
найденного здесь, на GitHub.
Установить: pip install django-bulk-update
Реализация: (код, полученный непосредственно из файла ReadMe проектов)
from bulk_update.helper import bulk_update
random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
r = random.randrange(4)
person.name = random_names[r]
bulk_update(people) # updates all columns using the default db
Обновление: Как отмечает Марк, комментарии не подходят для обновления сразу нескольких тысяч строк. Хотя он подходит для небольших партий от 10 до 100. Размер пакета, который подходит вам, зависит от вашего процессора и сложности запросов. Этот инструмент больше похож на кузов колес, чем на самосвал.
Ответ 3
В версии Django 2.2 теперь есть метод bulk_update
(примечания к выпуску).
https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-update
Пример:
# get a pk: record dictionary of existing records
updates = YourModel.objects.filter(...).in_bulk()
....
# do something with the updates dict
....
if hasattr(YourModel.objects, 'bulk_update') and updates:
# Use the new method
YourModel.objects.bulk_update(updates.values(), [list the fields to update], batch_size=100)
else:
# The old & slow way
with transaction.atomic():
for obj in updates.values():
obj.save(update_fields=[list the fields to update])
Ответ 4
Если вы хотите установить одно и то же значение в коллекции строк, вы можете использовать метод update() в сочетании с любым термином запроса, чтобы обновить все строки в одном запросе:
some_list = ModelClass.objects.filter(some condition).values('id')
ModelClass.objects.filter(pk__in=some_list).update(foo=bar)
Если вы хотите обновить коллекцию строк с различными значениями в зависимости от некоторых условий, вы можете в лучшем случае пакетировать обновления в соответствии со значениями. Допустим, у вас есть 1000 строк, в которых вы хотите установить для столбца одно из значений X, тогда вы можете заранее подготовить пакеты, а затем только выполнить X запросов на обновление (каждая по сути имеет форму первого примера выше) + начальный SELECT -query.
Если каждая строка требует уникального значения, нет способа избежать одного запроса на обновление. Возможно, посмотрите на другие архитектуры, такие как CQRS/Event Sourcing, если вам нужна производительность в этом последнем случае.
Ответ 5
how to update all value of any user getting user id
match=Insert.objects.get(uid=id)
if request.method=="POST":
firstName=request.POST.get('FirstName')
lastName=request.POST.get('LastName')
Phone=request.POST.get('Phone')
Address=request.POST.get('Address')
UserName=request.POST.get('UserName')
Password=request.POST.get('Password')
Email=request.POST.get('Email')
Insert.objects.filter(uid=id).update(firstName='hello')
return redirect(request,'perform/alldata.html')