Django - django.core.exceptions.FieldDoesNotExist - не существует поля с именем
На нашем производственном сервере мы получили следующую ошибку при перезапуске django или попытке запустить 'python manage.py makemigrations'
django.core.exceptions.FieldDoesNotExist: pricing.pricing has no field named 'price_per_hour'
Что странно, так это то, что поле price_per_hour было давно переименовано в price и миграция при этом прошла успешно.
Но теперь я получаю эту ошибку каждый раз и она мешает сделать любую другую модификацию модели (в любом приложении) и миграции.
Что я проверил :
Если я запускаю 'python manage.py showmigrations', каждая миграция отмечается X, что, если я прав, означает, что все миграции были выполнены
.price_per_hour больше не встречается/используется ни в одном из приложений/классов django
class Pricing(models.Model):
price = models.DecimalField(default=5,max_digits=10, decimal_places=2)
class Meta:
ordering = ['-price',]
def __str__(self):
return "{}".format(self.price)
- Я также экспортировал базу данных matching./current в sql и мы видим, что она содержит колонку price, а не price_per_hour. И нигде нет ссылки на price_per_hour .
CREATE TABLE public.pricing_pricing (
id integer NOT NULL,
price numeric(10,2) NOT NULL,
);
- Я также попытался на всякий случай переименовать введенную цену в price_per_hour, но это не помогло .
Мне кажется, что ошибка исходит от Django, а не от базы данных PostgreSQL, но я не уверен.
Я не знаю, что еще нужно искать, поэтому любая идея или предложение будут очень признательны
PS : Я думал удалить все файлы миграции и запустить их заново, но поскольку это рабочий сервер, я боюсь потерять содержимое базы данных или что-то сломать.
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc" -delete
Ошибка обнаружена в строке migrations/operations/fields. Каким-то образом произошло расхождение между базой данных и файлами миграций, или, возможно, вы применили команду RunPython в вашем файле миграции, которая ссылается на это поле.
Я тоже столкнулся с подобной проблемой, и в моем случае, похоже, дело было в создании и удалении определенного поля в двух старых файлах миграции.
Решением для вас является "исправление" старых файлов миграции, или уничтожение вашей истории.
Вариант 1) Для исправления ошибки потребуется просмотреть все файлы миграций и вручную отредактировать миграции, в которых возникает эта ошибка. Если вы сможете запустить команду makemigration в локальном редакторе в режиме отладки, вы сможете отследить, где возникает эта ошибка. К сожалению, руководство Django по этим ошибкам не такое подробное.
Вариант 2) Более простой вариант, тот, который я бы выбрал, - это раздавить файлы миграции. Таким образом, вы удаляете всю историю файлов миграции и сводите ее к одному шагу миграции. См. docs. Недостатком является то, что вы теряете всю историю, поэтому убедитесь, что ваша локальная среда, среда постановки и производственная среда синхронизированы. В частности, на производстве убедитесь, что модель базы данных (если вы используете postgres, вы можете использовать pgadmin) точно такая же, как ваша модель Django, показанная в коде.
Скачивание файлов миграции фактически удаляет всю историю. В вашем примере, если у вас есть миграция для добавления поля price_per_hour, и миграция для переименования этого поля позже в price, сминание объединит эти файлы миграции в одно действие, которое сделает поле price.
Итак, то, что описал Борис, было проблемой, с которой я столкнулся. В файлах миграции были несоответствия, и django не мог сделать миграции.
Точнее говоря, в моем случае ошибка "pricing.pricing не имеет названного поля" была связана с тем, что в первоначальном файле миграции поле было названо price, но во втором файле миграции было предложено переименовать price_per_hour (которого не существовало) в price и поэтому возникла ошибка
0001_initial.py
migrations.CreateModel(
name='Pricing',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('price', models.DecimalField(decimal_places=2, default=5, max_digits=10)),
0002_auto_20200304_1344.py
operations = [
migrations.RenameField(
model_name='pricing',
old_name='price_per_hour',
new_name='price',
),
Так что оба варианта, описанные Борисом, являются теми, которым следует следовать. Сначала вы можете попробовать пройтись по всем файлам миграций и, надеюсь, найти и исправить ошибку вручную. Чтобы выяснить, какой из них вызывает проблемы, я сделал следующее https://stackoverflow.com/a/53135777/20025351
И если вы можете исправить это вручную (это был мой случай), я убедился, что модель базы данных соответствует моделям Django, затем я удалил все файлы миграций и повторно запустил migration/migrate.