Django ORM, CharField и blank = True

Документация Django вполне понятна для хранения пустых строк как "", а не NULL на уровне базы данных (поэтому существует только один возможный формат для пустых данных):

Обратите внимание, что пустые значения строки всегда будут храниться как пустые строки, а не как NULL. Используйте только null = True для нестрочных полей, таких как целые числа, логические значения и даты. Для обоих типов полей вам также необходимо установить blank = True, если вы хотите разрешить пустые значения в формах, поскольку нулевой параметр влияет только на хранилище базы данных (см. Пробел).

Тем не менее, после добавления нового поля, я начал сталкиваться с IntegrityErrors в новом поле (номер телефона).

Значение null в столбце "phone_number" нарушает ненулевое ограничение

Эта модель выглядит так с новым полем (я выполнил миграцию через юг):

class Person(models.Model):
    user = models.ForeignKey(User)
    description = models.TextField(blank=True)
    phone_number = models.CharField(blank=True)

С тех пор я (временно) решил проблему, установив null = True в phone_number, но теперь у меня есть сотни записей с пустыми строками и одно значение NULL в моей базе данных. (Я также попытался добавить default = '' в поле phone_number, но я все еще видел проблемы IntegrityError.)

В прошлом я всегда использовал MySQL, но в этом проекте я использую Postgres. Сгенерированная попытка вставки SQL:

'INSERT INTO "people_person" ("user_id", "description", "gender", "birthdate", "default_image_id", "zip_code", "beta_status") VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING "people_person"."id"'.

Я ожидал, что Django будет вставлять пустую строку в столбец "phone_number", но, похоже, это не так. Другая вещь, которую я мог ожидать, - это Django, чтобы включить SET DEFAULT в оператор CREATE TABLE, но это не так. Поэтому Postgres рассердился на NOT NULL в этой колонке.

Спасибо!

Ответ 1

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

В моем приложении было две точки входа - два файла WSGI, но только одна база кода. Обычно Apache перезагружает ваш код только в том случае, если файл затронут. Мое развертывание script касалось только одного из этих файлов WSGI - это означало, что люди, которые дошли до моего сайта через другой файл WSGI, все еще видели старый код. Хуже того, база данных была изменена в соответствии с этим старым кодом, но модели были такими же, как и раньше.

Это, в свою очередь, вызвало проблемы IntegrityError. Django не знал о поле phone_number, поэтому, несмотря на то, что я установил blank=True, Django не прилагал усилий, чтобы вставить пустое значение, - и, конечно, база данных считала, что это означает NULL.

Это вызвало ряд различных ошибок отслеживания, включая указанную выше ошибку.

Удивительно, как часто очень сложные проблемы, подобные этим, вызваны глупыми незначительными упущениями - как развернуть script, я написал 2 месяца назад и забыл обновить.

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

Ответ 2

Я обнаружил, что если вы явно установите значение поля None, вы все равно получите эти ошибки. Другими словами, приложение default= применяется, как только вы создаете объект python, а затем, когда вы сохраняете его в базе данных.

Я предполагаю, что это разумно, но это было немного неожиданно.