Вы пытаетесь добавить не допускающее значения NULL поле new_field в userprofile без значения по умолчанию

109

Я знаю, что из Django 1.7 мне не нужно использовать Юг или любую другую систему миграции, поэтому я просто использую простую команду python manage.py makemigrations

Однако все, что я получаю, это ошибка:

You are trying to add a non-nullable field 'new_field' to userprofile without a default;
we can't do that (the database needs something to populate existing rows).

Вот models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True)
    new_field = models.CharField(max_length=140)

Какие есть варианты?

Ирмантас Желионис
источник
3
Я хотел добавить, что проблема возникает при изменении существующей таблицы, а не при создании новой.
x-

Ответы:

93

Вам необходимо указать значение по умолчанию:

new_field = models.CharField(max_length=140, default='SOME STRING')
dgel
источник
Что делать, если мне нужно, чтобы new_field была копией поля веб-сайта. Как это должно выглядеть? default = websiteне выполняет свою работу
Ирмантас Желионис 03
8
Вы можете сначала выполнить миграцию с фиктивным значением по умолчанию, а затем создать миграцию данных для итерации по каждой записи и установить new_fieldзначение website.
dgel 03
default должен быть необязательным для CharField
Florent
90

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

rm  your_app/migrations/*

rm db.sqlite3
python manage.py makemigrations
python manage.py migrate
Томаш
источник
8
Еще кое-что. Вам нужно очистить таблицу миграций, например:mysql -u[user] [database] -e "delete from django_migrations where app=[your_app]"
helpse
Это способ. Я думаю, что Django плохо справляется с миграцией, обнаружением модели и т. Д. Хочу серьезного обновления для этого.
WesternGun
Я удалил все файлы из миграций и удалил все строки из django_migrations, и теперь я получаю "django.db.migrations.exceptions.NodeNotFoundError: Migration stories. 0001_initial dependencies ссылаются на несуществующий родительский узел ('sources', '0002_auto_20180903_1224')" при запуске миграция.
brainLoop
1
Также убедитесь, что вы не __init__.py удалили файл из миграций или не восстановили его впоследствии, иначе makemigrations не будет работать stackoverflow.com/a/46362750/1649917
nmu
python manage.py sqlmigrate name_of_your_app nb_of_the_migrationтакже требуется
zar3bski
38

Один из вариантов - объявить значение по умолчанию для new_field:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE')

другой вариант - объявить new_field как поле, допускающее значение NULL:

new_field = models.CharField(max_length=140, null=True)

Если вы решите принять «new_field» как поле, допускающее значение NULL, вы можете принять «no input» как допустимый ввод для «new_field». Затем вам нужно также добавить blank=Trueоператор:

new_field = models.CharField(max_length=140, blank=True, null=True)

Даже с null=Trueи / или при необходимости blank=Trueвы можете добавить значение по умолчанию:

new_field = models.CharField(max_length=140, default='DEFAULT VALUE', blank=True, null=True)
Тоби
источник
7
«Избегайте использования null в строковых полях, таких как CharField и TextField. Если строковое поле имеет значение null = True, это означает, что оно имеет два возможных значения для «нет данных»: NULL и пустая строка ». - Ссылка на поле модели
Chema
7

Если вы находитесь на ранней стадии разработки, вы можете попробовать это -

Удалите / прокомментируйте эту модель и все ее использования. Примените миграции. Это удалит эту модель, а затем снова добавит ее, запустит миграции, и у вас будет чистая модель с добавленным новым полем.

Суровый
источник
И очистите таблицу миграции django_migrations, как описано здесь: stackoverflow.com/questions/26185687/… Или просто используйте графический интерфейс и удалите необходимые строки.
RusI
5

В случае, если кто-то устанавливает a ForeignKey, вы можете просто разрешить поля, допускающие значение NULL, без установки значения по умолчанию:

new_field = models.ForeignKey(model, null=True)

Если у вас уже есть данные, хранящиеся в базе данных, вы также можете установить значение по умолчанию:

new_field = models.ForeignKey(model, default=<existing model id here>)
Джастин Ланге
источник
4

Если «веб-сайт» может быть пустым, он new_fieldтакже должен быть пустым.

Теперь, если вы хотите добавить логику для сохранения, где если new_fieldпусто, чтобы получить значение с «веб-сайта», все, что вам нужно сделать, это переопределить функцию сохранения для вас, Modelнапример:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True, default='DEFAULT VALUE')
    new_field = models.CharField(max_length=140, blank=True, default='DEFAULT VALUE')

    def save(self, *args, **kwargs):
        if not self.new_field:
            # Setting the value of new_field with website's value
            self.new_field = self.website

        # Saving the object with the default save() function
        super(UserProfile, self).save(*args, **kwargs)
Алекс Карлос
источник
3

Вы не можете добавить ссылку на таблицу, в которой уже есть данные.
Изменить:

user = models.OneToOneField(User)

кому:

user = models.OneToOneField(User, default = "")

делать:

python manage.py makemigrations
python manage.py migrate

снова изменить:

user = models.OneToOneField(User)

выполните миграцию еще раз:

python manage.py makemigrations
python manage.py migrate
Э. Кристийоно
источник
2

В new_file добавьте логическое свойство null.

new_field = models.CharField(max_length=140, null=True)

после запуска ./manage.py syncdbдля обновления БД. и наконец ты бежишь ./manage.py makemigrations и./manage.py migrate

герачев
источник
2

Вы можете использовать метод из Django Doc с этой страницы https://docs.djangoproject.com/en/1.8/ref/models/fields/#default

Создать по умолчанию и использовать его

def contact_default():
   return {"email": "to1@example.com"}

contact_info = JSONField("ContactInfo", default=contact_default)
Денис Савенко
источник
2

У вас уже есть записи базы данных в таблице UserProfile? Если да, то когда вы добавляете новые столбцы, БД не знает, что это делать, потому что это невозможно NULL. Поэтому он спрашивает, что вы хотите установить для этих полей в столбце new_fields. Мне пришлось удалить все строки из этой таблицы, чтобы решить проблему.

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

Арнольд Лам
источник
1
Я не вставлял строки в таблицу и до сих пор получаю это. Мне нужно удалить всю историю миграции, очистить таблицу миграции, чтобы изменить модель, как предложил Томаш.
WesternGun
1

Честно говоря, я нашел, что лучший способ обойти это - просто создать другую модель со всеми необходимыми полями и немного другими именами. Запустите миграции. Удалите неиспользуемую модель и снова запустите миграции. Вуаля.

Джош
источник
1

Если вас устраивает усечение таблицы рассматриваемой модели, вы можете указать Noneв приглашении одноразовое значение по умолчанию . Миграция будет лишней, default=Noneпока в вашем коде нет значения по умолчанию. Его можно применить просто так, потому что в таблице больше нет данных, которые требовали бы значения по умолчанию.

jnns
источник
1

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

Я добавил blank=True, null=Trueв столбцы, где получал ошибку. Затем я выполнил python manage.py makemigrationsкоманду.

Сразу после выполнения этой команды (и перед запуском python manage.py migrate) я удалил blank=True, null=Trueиз всех столбцов. Затем я побежалpython manage.py makemigrations снова . Мне дали возможность просто изменить столбцы самостоятельно, которые я выбрал.

Потом побежал python manage.py migrateи все заработало!

Джозеф Гилл
источник
0

На самом деле Django говорит:

В таблице Userprofile есть данные, и могут быть new_fieldзначения, которые равны NULL, но я не знаю, поэтому вы уверены, что хотите пометить свойство как не допускающее значение NULL, потому что в этом случае вы можете получить ошибку, если есть значения с NULL

Если вы уверены, что ни одно из значений в userprofileтаблице не является NULL - выпали и игнорируйте предупреждение.

Лучшей практикой в ​​таких случаях было бы создание миграции RunPython для обработки пустых значений, как указано в варианте 2.

2) Пока не обращайте внимания, и позвольте мне обрабатывать существующие строки с NULL самостоятельно (например, потому что вы добавили операцию RunPython или RunSQL для обработки значений NULL в предыдущей миграции данных)

В миграции RunPython вы должны найти все UserProfileэкземпляры с пустым new_fieldзначением и поместить туда правильное значение (или значение по умолчанию, которое Django просит вас установить в модели). Вы получите что-то вроде этого:

# please keep in mind that new_value can be an empty string. You decide whether it is a correct value.
for profile in UserProfile.objects.filter(new_value__isnull=True).iterator():
    profile.new_value = calculate_value(profile)
    profile.save() # better to use batch save

Радоваться, веселиться!

Тарас Мацык
источник
Я не могу найти, где это написано в документации. Не могли бы вы опубликовать ссылку, пожалуйста?
Коди
0

В models.py

class UserProfile(models.Model): user = models.OneToOneField(User) website = models.URLField(blank=True) new_field = models.CharField(max_length=140, default="some_value")

Вам нужно добавить некоторые значения по умолчанию.

Джордж Девасия
источник
-1

Если SSH дает вам 2 варианта, выберите номер 1 и поставьте «Нет». Только это ... на данный момент.

Джеованни Атавалес
источник