Как "массовое обновление" с помощью 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')