выбрать и обновить запись базы данных с помощью одного набора запросов

140

Как мне запустить операторы updateи selectна одном и том же, querysetвместо того, чтобы выполнять два запроса: - один для выбора объекта - и один для обновления объекта

Эквивалент в SQL будет примерно таким:

update my_table set field_1 = 'some value' where pk_field = some_value
Джон
источник

Ответы:

269

Используйте метод объектаupdate queryset :

MyModel.objects.filter(pk=some_value).update(field1='some value')
Даниэль Роузман
источник
96
Просто честно предупреждение ... если вы используете такой updateметод, тогда никакие сигналы, прикрепленные к этой модели или другому «материалу кода», не будут работать с объектами. Просто указатель от того, кто обгорел :)
DMac the Destroyer
@DMactheDestroyer, чувак, спасибо за эту ценную информацию. Тогда следует ли нам использовать старый способ его обновления? (т.е.) получить и сэкономить?
@ хорошо учишься, чувак, все зависит от твоего сценария. Этот updateметод отлично подходит для массовых обновлений, но он должен вызвать предупреждение в вашей голове, когда вы его используете, что вам нужно просмотреть любые сигналы, прикрепленные к этому объекту, которые, возможно, также потребуется
запустить
3
Можно ли получить доступ к текущему экземпляру модели в функции обновления? нравитсяMyModel.objects.filter(pk=some_value).update(field1=self.data)
Дипак
8
@DipakChandranP Вам следует задать новый вопрос, а не комментировать вопрос шестилетней давности. Но выражения F (), вероятно, вам нужны.
Daniel Roseman
70

Объекты базы данных Django используют один и тот же метод save () для создания и изменения объектов.

obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()

Как Django знает, что нужно делать UPDATE или INSERT.
Если для атрибута первичного ключа объекта установлено значение True (то есть значение, отличное от None или пустой строки), Django выполняет UPDATE. Если атрибут первичного ключа объекта не установлен или если UPDATE ничего не обновляет, Django выполняет INSERT.

Ссылка: https://docs.djangoproject.com/en/1.9/ref/models/instances/

Slipstream
источник
17

В этом ответе сравниваются два вышеуказанных подхода. Если вы хотите обновить несколько объектов в одной строке, выполните:

# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')

В противном случае вам придется перебирать набор запросов и обновлять отдельные объекты:

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. Подход 1 быстрее, потому что он выполняет только один запрос к базе данных, по сравнению с подходом 2, который делает запросы к базе данных n + 1. (Для n элементов в наборе запроса)

  2. Первый подход делает один запрос к БД, т.е. ОБНОВЛЕНИЕ, второй - два: ВЫБРАТЬ, а затем ОБНОВИТЬ.

  3. Компромисс заключается в том, что, предположим, у вас есть какие-либо триггеры, такие как обновление updated_onили любые подобные связанные поля, они не будут запускаться при прямом обновлении, то есть подходе 1.

  4. Подход 1 используется в наборе запросов, поэтому можно обновлять сразу несколько объектов, а не в случае подхода 2.

Пранш Тивари
источник
Что касается 1. - Я думаю, что результат запроса кэшируется при первом вызове запроса, поэтому на самом деле все еще остается только один вызов БД.
user2340939
2

только в случае с serializerвещами, можно очень просто обновить!

my_model_serializer = MyModelSerializer(
    instance=my_model, data=validated_data)
if my_model_serializer.is_valid():

    my_model_serializer.save()

только в случае в formвещах!

instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
    form.save()
Джамиль Нойда
источник
Я думаю, что сериализаторы взяты из Djanog Rest Framework, а не из Django.
Code-Apprentice,
1
Да, но Django formот Django Proper.
Джамиль Нойда,