Ошибка переноса Django: столбца не существует

Python 3, Django 1.8.5, Postgres

У меня есть модель Sites, которая работает нормально. Недавно я попытался добавить поле, airport_code и перенести данные.

class Site(BaseModel):

  objects = SiteManager()

  name = models.CharField(max_length=200, unique=True)
  domain = models.CharField(max_length=200, unique=True)
  weather = models.CharField(max_length=10)
  nearby_sites = models.ManyToManyField('self', symmetrical=False, blank=True)
  users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
  facebook = models.URLField(max_length=200)
  twitter = models.URLField(max_length=200)
  header_override = models.TextField(blank=True)
  email_header_override = models.TextField(blank=True)
  timely_site_tag_id = models.IntegerField()
  timely_featured_tag_id = models.IntegerField()
  timely_domain = models.CharField(max_length=255)
  sitemap_public_id = models.CharField(max_length=255)
  state = models.CharField(max_length=24)
  airport_code = JSONField()

Однако, когда я запустил makemigrations, я получил сообщение об ошибке:

django.db.utils.ProgrammingError: column sites_site.airport_code does not exist LINE 1: ..._site"."sitemap_public_id", "sites_site"."state", "sites_sit...

Конечно, это не имеет смысла, потому что столбец, очевидно, не существует, когда я пытаюсь создать его в процессе миграции.

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

Ответ 1

Эта ошибка была решена для меня, комментируя панель инструментов отладки django из INSTALLED_APPS в settings.py. Я не уверен, почему панель инструментов отладки является виновником, но после того, как я прокомментировал это, я смог запустить makemigrations и migrate без проблем.

Надеясь, что это помогает кому-то, поскольку я провел двенадцать часов, пытаясь понять это.

Ответ 2

После запуска makemigrations, не забудьте пройти трассировку стека шаг за шагом.

В моем случае я заметил, что он отслеживается путем вызова формы, содержащейся в form.py, в совершенно другом приложении, которое вызвало вызов модели, с которой я пытался создать новую миграцию.

Перемещение класса Form из формы .py в view.py устраняет проблему.

Ответ 3

В моем случае это было связано с тем, что у меня было установлено ограничение unique_together.

Когда я захотел удалить поле, автоматически сгенерированная миграция попыталась удалить поле перед удалением ограничения unique_together.

То, что мне нужно было сделать, это вручную переместить ограничение миграций.AlterUniqueTogether в файле миграции, так что django сначала удаляет ограничение, прежде чем пытаться удалить поле.

Я надеюсь, что это может кому-то помочь.

Ответ 4

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

У меня есть модель Brand следующим образом:

class Brand(BaseModelClass):
    name = CharField(max_length=256, unique=True)
    website = ForeignKey(URL, on_delete=CASCADE, null=True, blank=True)

Я запустил python manage.py makemigrations после добавления Boolean поля следующим образом:

class Brand(BaseModelClass):
    name = CharField(max_length=256, unique=True)
    website = ForeignKey(URL, on_delete=CASCADE, null=True, blank=True)
    trusted = Boolean(default=True)

При выполнении команды makemigrations я получил ошибку, похожую на OP:

django.db.utils.ProgrammingError: column appname_brand.trusted does not exist

По предложению @Nexus, я прошёл стэк-трассировку, построчно, предполагая, что это не какая-то основная проблема с Django. Оказывается, в одном из файлов forms.py меня было следующее:

choices={(str(brand.id), brand.name) for brand in Brand.objects.all()}

Решением было просто закомментировать эту строку, запустить manage.py makemigrations, а затем запустить manage.py migrate. После этого я раскомментировал строку, и все и функциональность моих форм работали так же, как и раньше.

Ответ 5

У меня та же проблема (столбец не существует), но когда я пытаюсь запустить migrate не с makemigrations

  • Причина. Я удалил файлы миграции и заменил их одним исходным файлом начальной миграции 0001 перед запуском миграции для последнего изменения.

  • Решение:

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

И вот как решить эту проблему:

  • Войдите в систему как пользователь postgres (мой пользователь называется posgres):

    sudo -i -u postgres

  • Откройте терминал SQL и подключитесь к вашей базе данных:

    psql -d database_name

  • Перечислите свою таблицу и найдите таблицы, связанные с этим приложением:

    \dt

  • Отбросьте их (рассмотрите порядок удаления с отношениями):

    DROP TABLE tablename ;

  • Перечислите запись миграции, вы увидите, что примененные миграции классифицированы так:

id | приложение | имя | прикладная
- + ------ + -------- + --------- +

SELECT * FROM django_migrations;
  • Удалить строки миграции этого приложения (вы можете удалить по идентификатору или по приложению, с приложением не забывайте "кавычки"):

    DELETE FROM django_migrations WHERE app='your_app';

  • Выйдите из системы и запустите ваши миграции (возможно, запустите makemigrations в вашем случае):

    python manage.py migrate --settings=your.settings.module_if_any

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

Я хотел бы, чтобы это могло помочь.

Ответ 6

Я столкнулся с этой проблемой недавно после обновления до Django 1.11. Я хотел навсегда решить эту проблему, чтобы мне не приходилось комментировать/раскомментировать код каждый раз, когда я запускаю миграцию на столе, поэтому мой подход:

from django.db.utils import ProgrammingError as AvoidDataMigrationError

try:
    ... do stuff that breaks migrations
except AvoidDataMigrationError:
    pass

Я переименую исключение во время импорта в AvoidDataMigrationError чтобы было понятно, почему оно там.

Ответ 7

Убедитесь, что вы не выполняете никаких запросов при загрузке приложения!, например. в:

class A:
  field = fn_that_makes_query()

При запуске migrate или makemigrations Django выполняет системные проверки, которые загружают все приложение, поэтому, если в ходе этого процесса будут выполнены какие-либо запросы, использующие добавленные/измененные поля БД, вы столкнетесь с непредвиденными обстоятельствами, потому что вы пытаетесь получить доступ к файлам базы данных, которых еще нет.

Ответ 8

Запустите эту проблему после переноса моей базы данных postgres на другой сервер. Как-то я испортил базу данных и не смог обновить мою модель с помощью нового класса UserProfile.

Я решил проблему создания начальной миграции для существующей схемы:

  • Очистите таблицу django_migrations: delete from django_migrations; командой DELETE FROM django_migrations WHERE app='my_app';
  • Для каждого приложения удалите его папку migrations: rm -rf <app>/migrations/
  • Reset миграции для "встроенных" приложений: python manage.py migrate --fake
  • Для каждого запуска приложения: python manage.py makemigrations <app>. Позаботьтесь о зависимостях (модели с ForeignKey должны запускаться после их родительской модели).
  • Наконец: python manage.py migrate --fake-initial

Получил его здесь: fooobar.com/questions/96343/...

PS Я не уверен, что это имело отношение к разрешению проблемы, но, во-первых, я отбросил таблицу в postgresql, которая вызвала ошибку, и закомментировала класс UserProfile в моделях.

в оболочке:

 sudo -su postgres
 psql databse_name   
 DROP TABLE table_name;

models.py:

#class UserProfile(models.Model):
    #user = models.OneToOneField(settings.AUTH_USER_MODEL, unique=True, primary_key=True, on_delete=models.CASCADE, related_name='user_profile')
    #avatar = ThumbnailerImageField(upload_to='profile_images', blank=True)
    #country = models.CharField(max_length = 128)

Ответ 9

Застрял в этом вопросе недавно.

В моем случае я добавил ссылку на несуществующее поле в коде, затем пришел к файлу модели и добавил новое поле, затем попытался запустить команду makemigrations которая makemigrations вышеуказанную ошибку.

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

Ответ 10

Просто сейчас была та же ошибка, когда я пытался перенести SingletonModel, чтобы фактически содержать необходимые поля.

Причиной ошибки было то, что моя Модель A использовала некоторые поля этой модели SingletonModel (в качестве настраиваемых значений). И во время создания модели А в процессе миграции это явно не могло гарантировать, что моя миграция была безопасной.

У коллеги была замечательная идея. Сделайте значение по умолчанию для поля вызовом функции, и, следовательно, ленивым.

Пример:

class A (models.Model):
    default_value = models.DecimalField(default: lambda: SingletonModel.get_solo().value, ...)

Поэтому мой совет: попробуйте сделать вызов, вызывающий оскорбления (видимый в stacktrace), ленивым.