Ответ
Да, для выборочного обновления полей модели при вызове метода save() используется аргумент update_fields. Он принимает список строк с именами полей, которые необходимо обновить в базе данных.
Почему это важно?
- Производительность: Генерируется более легковесный SQL-запрос
UPDATE, который затрагивает только указанные столбцы. - Предотвращение гонки данных (Race Conditions): Если другой процесс изменил поле, которое вы не собирались трогать, передача
update_fieldsгарантирует, что вы не перезапишете его значение случайно. - Работа с сигналами: Сигналы будут вызваны, но могут работать с неполным состоянием объекта.
Пример использования:
from myapp.models import MyModel
# Получаем существующий объект
obj = MyModel.objects.get(pk=1)
# Изменяем несколько полей в объекте Python
obj.name = 'Новое имя'
obj.counter = 10
# Сохраняем в БД только поле 'name'
# Изменение поля 'counter' будет проигнорировано
obj.save(update_fields=['name'])
Ключевые моменты:
- Параметр
update_fieldsработает только при обновлении существующих объектов и игнорируется при создании нового (при первом вызовеsave()). - Поля с
auto_now=True(например,DateTimeField) будут обновлены всегда, даже если их нет в спискеupdate_fields. - Если
update_fieldsпуст ([]), сохранение не произойдет.
Для массовых обновлений без загрузки объектов в память эффективнее использовать метод update() у QuerySet:
MyModel.objects.filter(pk=1).update(name='Новое имя')
Ответ 18+ 🔞
А, слушай, вот эта штука с update_fields в save() — это вообще огонь, если знать, зачем она нужна. Не просто так же её придумали, эти, блядь, архитекторы Django.
Представь себе: у тебя объект, как этот Герасим, здоровый такой, с кучей полей. И ты ему меняешь, допустим, только имя. А он у тебя в памяти уже весь, со всеми своими счётчиками, датами и прочей хуйнёй, которую ты трогать не собирался.
Если ты просто сделаешь obj.save(), Django, такой: «О, бля, объект изменился! Надо всё обновить!» И погонит в базу здоровенный UPDATE, который перезапишет все поля, даже те, что ты не менял. А если за это время другой процесс, какой-нибудь полупидор, уже успел изменить тот же счётчик? Пиздец, Колян! Твоё старое значение из памяти просто затрет его правки. Вот это и есть гонка данных, ебать её в сраку.
А вот если ты скажешь save(update_fields=['name']), то Django, умный такой, сгенерит запрос только для одного поля: UPDATE ... SET name='Новое имя' WHERE id=1;. И всё. Быстро, чисто, и чужой счётчик останется цел. Производительность — овердохуища, особенно если полей много.
obj = MyModel.objects.get(pk=1)
obj.name = 'Новое имя' # Меняем только это
obj.counter = 999 # А это меняем просто так, для души
# Сохраняем в БД ТОЛЬКО имя. Поле counter в базу не улетит.
obj.save(update_fields=['name'])
Но, блядь, есть нюансы, конечно, ёпта:
- Эта магия работает только при апдейте. Создаёшь новый объект —
update_fieldsигнорируется, иди нахуй. - Поля с
auto_now=True— те ещё суки. Они обновятся всегда, даже если их в списке нет. Хитрые жопы. - Если передашь пустой список
[]— сохранения вообще не будет. Ну, типа, «чё обновлять-то?».
А если тебе надо просто по-быстрому сменить значение у кучи записей, даже не вытаскивая их в память, то тут save() с update_fields — это как молотком гвозди забивать. Есть же метод update() у QuerySet! Вот это — снайперская винтовка.
MyModel.objects.filter(pk=1).update(name='Новое имя')
Бабах — и в базе уже новое имя, без всяких танцев с бубном вокруг Python-объектов. Красота, блядь. Главное — инструмент под задачу выбирай, а то мартышлюшкой прослывёшь.