Добавление дополнительных ограничений в поля в Django - PullRequest
27 голосов
/ 17 февраля 2010

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

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

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

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

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

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

Ответы [ 4 ]

47 голосов
/ 17 февраля 2010

Я бы не ставил подобные ограничения в методе сохранения, слишком поздно. Возникновение исключения не помогает пользователю, который неверно ввел данные, потому что в итоге получится 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')
11 голосов
/ 17 февраля 2010

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

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" 
10 голосов
/ 31 октября 2015

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

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

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

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

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

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

РЕДАКТИРОВАТЬ : Вы также можете просто сохранить время начала и продолжительность вместо времени начала и окончания.

2 голосов
/ 05 февраля 2018

На сегодняшний день, postgres 9.4 и MS SQL Server> = 2008 поддерживают ограничения проверки в sql.Кроме того, существует django выпуск 11964 , который, кажется, готов к рассмотрению со вчерашнего дня, так что, надеюсь, мы увидим это интегрированным в django 2. Проект rapilabs / django-db-constraints, кажется, реализует это тоже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...