Обновляйте только определенные поля в моделях.

92

У меня есть модель

class Survey(models.Model):
    created_by = models.ForeignKey(User)
    question = models.CharField(max_length=150)
    active = models.NullBooleanField()
    def __unicode__(self):
        return self.question

и теперь я хочу обновить только activeполе. Итак, я делаю это:

survey = get_object_or_404(Survey, created_by=request.user, pk=question_id)
survey.active = True
survey.save(["active"]) 

Теперь я получаю ошибку IntegrityError: PRIMARY KEY must be unique .

Правильно ли я с этим методом обновляюсь?

зарегистрированный пользователь
источник

Ответы:

187

Чтобы обновить подмножество полей, вы можете использовать update_fields:

survey.save(update_fields=["active"]) 

update_fieldsАргумент был добавлен в Django 1.5. В более ранних версиях update()вместо этого можно было использовать метод:

Survey.objects.filter(pk=survey.pk).update(active=True)
Alasdair
источник
17

Обычно правильный способ обновления определенных полей в одном или нескольких экземплярах модели - использовать update()метод в соответствующем наборе запросов. Затем вы делаете что-то вроде этого:

affected_surveys = Survey.objects.filter(
    # restrict your queryset by whatever fits you
    # ...
    ).update(active=True)

Таким образом, вам больше не нужно вызывать save()свою модель, потому что она сохраняется автоматически. Кроме того, update()метод возвращает количество экземпляров опроса, на которые повлияло ваше обновление.

пемисталь
источник
2
Спасибо. Я пробовал .getвместо, .filterи это не работает. Но с фильтром все работает нормально. Вы знаете, что не так с моим приведенным выше кодом?
Зарегистрированный пользователь
Ваша проблема может быть связана с question_id. Откуда взялось это значение? И какая именно линия поднимает IntegrityError?
pemistahl
question_idисходит из URL-адресов (?P<question_id>\d+). Моя ошибка заключалась в том, что на рабочем сервере установлен django 1.4, а мой код - 1.5. Но с вашим кодом все работает нормально.
Зарегистрированный пользователь
2
@RegisteredUser, похоже, нет метода «обновления» для объектов, только для наборов запросов. Когда вы используете .filter (), вы получаете набор запросов (содержащий ноль или более объектов). Когда вы используете .get (), вы получаете единственный объект.
mgojohn
По умолчанию вызов save()(решение @Alasdair) является более безопасным решением, потому что этот метод может запускать такие вещи, как проверка или любой пользовательский код, чем update()нет.
Дэвид Д.