Ви намагаєтесь додати до нульового поля "new_field" поле користувача newprofile без типових умов


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-yuri

Відповіді:


91

Потрібно вказати значення за замовчуванням:

new_field = models.CharField(max_length=140, default='SOME STRING')

Що робити, якщо мені потрібно мати new_field копію поля веб-сайту. Як це має виглядати? default = websiteне виконує роботу
Ірмантас Жеміоніс

8
Ви хочете спершу зробити міграцію з фальшивим значенням за замовчуванням, а потім створити міграцію даних для повторення через кожну запис та встановити new_fieldна website.
dgel

за замовчуванням має бути необов’язковим для CharField
Флорент

88

Якщо ви перебуваєте в ранньому циклі розробки і вам не байдуже поточні дані бази даних, ви можете просто їх видалити, а потім перемістити. Але спочатку потрібно очистити міграцію dir та видалити її рядки з таблиці (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

Це шлях. Я думаю, що Джанго смокче міграцію та виявлення моделей тощо.
WesternGun

Я видалив усі файли під час міграцій та видалив усі рядки з django_migramigra, і тепер я отримую "django.db.migrations.exceptions.NodeNotFoundError: Історії міграції.0001_initial залежність посилання на неіснуючий батьківський вузол ('джерела', '0002_auto_20180903_1224')" міграція.
brainLoop

1
Також переконайтеся , що ви не видалити __init__.py з міграції, або, ви відновити його згодом, в іншому випадку makemigrations не працюватиме stackoverflow.com/a/46362750/1649917
НММ

python manage.py sqlmigrate name_of_your_app nb_of_the_migrationтакож потрібно
zar3bski

37

Один варіант - оголосити значення за замовчуванням для 'new_field':

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

інший варіант - оголосити "new_field" як нульове поле:

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

Якщо ви вирішили прийняти "new_field" як нульове поле, ви можете прийняти "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
«Уникайте використання нуля для полів на основі рядків, таких як CharField та TextField. Якщо поле, засноване на рядках, має null = True, це означає, що у нього є два можливих значення для "no data": NULL та порожня рядок. " - Посилання на модель моделі
Chema

7

Якщо ви рано в циклі розвитку, ви можете спробувати це -

Видаліть / коментуйте цю модель та всі її звичаї. Застосовуйте міграції. Це видалить цю модель, а потім додасть її знову, запустіть міграції, і у вас буде додана чиста модель з новим полем.


І очистіть таблицю міграцій django_migrations, як зазначено тут: stackoverflow.com/questions/26185687/… Або просто скористайтеся графічним інтерфейсом та видаліть потрібні рядки.
Русь

5

У випадку, якщо хтось встановить a ForeignKey, ви можете просто дозволити нульові поля без встановлення за замовчуванням:

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 додайте boolean властивість null.

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

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



2

У вас уже є записи в базі даних у таблиці UserProfile? Якщо так, коли ви додаєте нові стовпці, БД не знає, для чого його встановити, оскільки цього не може бути NULL. Тому він запитує, на що ви хочете встановити ці поля в стовпці new_fields. Для вирішення проблеми мені довелося видалити всі рядки з цієї таблиці.

(Я знаю, що на це відповіли деякий час тому, але я просто зіткнувся з цією проблемою, і це було моїм рішенням. Сподіваюся, це допоможе кожному, хто бачить це)


1
Я не вставив рядки в таблицю і досі отримую це. Я повинен видалити всю історію міграції, очистити таблицю міграції, щоб змінити модель, як запропонував Томаш.
WesternGun

1

Я, чесно кажучи, найкращим способом подолати це було просто створити іншу модель з усіма потрібними полями та названими трохи іншими. Запустити міграцію. Видаліть невикористану модель та запустіть міграцію знову. Вуаля.


1

Якщо ви добре обрізаєте таблицю відповідної моделі, ви можете вказати одноразове значення за замовчуванням Noneу підказці. Міграція буде зайвою, default=Noneпоки ваш код не має за замовчуванням. Його можна застосувати просто чудово, оскільки в таблиці більше немає даних, які потребували б дефолту.


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

Що насправді говорить Джанго:

Таблиця Userprofile містить дані в ній. Можуть бути new_fieldзначення, які є недійсними, але я не знаю, тому ви впевнені, що хочете позначити властивість як ненульову, тому що якщо у вас може виникнути помилка, якщо є значення з 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")

Потрібно додати деякі значення за замовчуванням.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.