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.

Вернуться на верх