Подтвердить что ты не робот

Добавление дополнительных ограничений в поля в Django

При подклассовке db.models.Model иногда необходимо добавить дополнительные проверки/ограничения.

например. У меня есть модель Event с start_date и end_date.

Я хочу добавить проверку в поля или модель, чтобы end_date > start_date.

Сколько возможных способов сделать это?

По крайней мере, я знаю, что это можно сделать вне models.Model внутри проверки ModelForm.

Но как присоединить к полям и models.Model?

4b9b3361

Ответ 1

Сделайте это внутри своего метода сохранения вашей модели:

def save(self, *args, **kwargs):
    if(self.end_date > self.start_date):
        super(Foo, self).save(*args, **kwargs)
    else:
        raise Exception, "end_date should be greater than start_date" 

Ответ 2

Я бы не поставил такие ограничения в методе сохранения, это слишком поздно. Создание исключения там не помогает пользователю, который ввел данные не так, потому что он закончится как 500, и пользователь не получит форму с ошибками и т.д.

Вы действительно должны проверить это в методе очистки Forms/ModelForms и поднять ValidationError, поэтому form.is_valid() возвращает false, и вы можете отправить ошибки в форме обратно пользователю для исправления.

Также обратите внимание, что с версии 1.2 Django имеет Проверка модели.

Он будет выглядеть примерно так:

class Foo(models.Model):
    #  ... model stuff...
    def clean(self):
        if self.start_date > self.end_date:
            raise ValidationError('Start date is after end date')

Ответ 3

Как говорит @stefanw, лучше проверить пользовательский способ очистки формы.

Этого достаточно, если вы уверены, что нет и никогда не будет другого способа изменить значение. Но поскольку вы редко можете быть в этом уверены, если важна согласованность базы данных, вы можете добавить еще одну проверку (в дополнение к форме), одну из следующих:

  • Более простой и независимый от базы данных способ находится в методе сохранения модели, как сказал @umnik700. Обратите внимание, что это все еще не мешает другим пользователям базы данных (другому приложению или интерфейсу администратора) создавать несогласованное состояние.
  • Чтобы быть полностью "уверенным, что база данных согласована, вы можете добавить ограничение уровня базы данных. Например. вы можете создать миграцию с помощью RunSQL и SQL, что-то вроде (не протестировано):

    migrations.RunSQL('ALTER TABLE app_event ADD CONSTRAINT chronology CHECK (start_date > end_date);')
    

    (не проверено). Это может быть зависимым от базы данных, что, конечно, является недостатком.

В вашем примере это, вероятно, не стоит (неправильные времена начала и окончания просто выглядят немного странно, но влияют только на одно несогласованное событие), и вы не хотите изменения ручной схемы. Но это полезно в тех случаях, когда согласованность имеет решающее значение.

EDIT. Вы также можете просто сохранить время начала и продолжительность, а не время начала и окончания.