вибір та оновлення запису бази даних за допомогою одного набору запитів


139

Як запустити updateта selectзаяви на одних і тих же, querysetа не робити два запити: - один для вибору об'єкта - і один для оновлення об'єкта

Еквівалент у SQL був би на кшталт:

update my_table set field_1 = 'some value' where pk_field = some_value

Відповіді:


267

Використовуйте метод об'єктаupdate набору запитів :

MyModel.objects.filter(pk=some_value).update(field1='some value')

95
Просто справедливе попередження ... якщо ви використовуєте такий updateметод, то будь-які сигнали, приєднані до цієї моделі чи інші "кодові речі", не будуть працювати проти об'єктів. Просто вказівник від того, хто отримав опік :)
DMac the Estroyer

@DMactheDestroyer чувак дякує за цю цінну інформацію. Тоді ми повинні використовувати старіший спосіб його оновлення? (тобто) дістати і заощадити?

@ учіться добре чувак, все залежить від вашого сценарію. updateМетод відмінно підходить для масових оновлень, але він повинен відправитися попередження у вашій голові , коли ви використовуєте його , що ви повинні розглянути будь-які сигнали , підключені до цього об'єкта , який , можливо , також повинен бути вручну звільнені
Удіс руйнівник

3
Чи можливий доступ до поточного екземпляра моделі у функції оновлення? якMyModel.objects.filter(pk=some_value).update(field1=self.data)
Діпак

8
@DipakChandranP Вам слід задати нове запитання, а не ставити коментарі до шестирічного віку. Але F () вирази, мабуть, хочете, що хочете.
Даніель Роузмен

70

Об'єкти бази даних Django використовують той самий метод save () для створення та зміни об'єктів.

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

Як Django знає UPDATE vs. INSERT
Якщо для атрибута основного ключа об'єкта встановлено значення, що визначається як True (тобто значення, відмінне від None, або порожній рядок), Django виконує UPDATE. Якщо атрибут первинного ключа об'єкта не встановлений або якщо UPDATE нічого не оновив, Django виконує ВСТУП.

Довідка: https://docs.djangoproject.com/en/1.9/ref/models/in вещества/


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. Підхід кулаком робить один db-запит, тобто UPDATE, другий - два: SELECT, а потім UPDATE.

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

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


Щодо 1. - Я думаю, що результат запиту кешується під час першого дзвінка на запит, отже, насправді є лише один виклик до БД.
користувач2340939

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, а не з Джанго.
Код-учень

1
Так, проте Django formвід Django Proper.
Джаміль Нойда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.