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)
  • 我还导出了匹配项/sql中的当前数据库,我们可以很好地看到它包含price列,而不是priceper_hour。任何地方都没有提到price_per_hour
CREATE TABLE public.pricing_pricing (
id integer NOT NULL,
price numeric(10,2) NOT NULL,
);
  • 我还试图将提交的价格重命名为price_per_hour,以防万一,但无济于事

对我来说,错误似乎来自Django,而不是PostgreSQL数据库,但我不确定。

以下是完整的回溯

python manage.py makemigrations
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 328, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 369, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python3.8/site-packages/django/core/management/base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/core/management/commands/makemigrations.py", line 141, in handle
loader.project_state(),
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/loader.py", line 324, in project_state
return self.graph.make_state(nodes=nodes, at_end=at_end, real_apps=list(self.unmigrated_apps))
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/graph.py", line 315, in make_state
project_state = self.nodes[node].mutate_state(project_state, preserve=False)
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/migration.py", line 87, in mutate_state
operation.state_forwards(self.app_label, new_state)
File "/usr/local/lib/python3.8/site-packages/django/db/migrations/operations/fields.py", line 326, in state_forwards
raise FieldDoesNotExist(
django.core.exceptions.FieldDoesNotExist: pricing.pricing has no field named 'price_per_hour'

我不知道还有什么其他的东西可以找,所以,任何想法或建议都会非常感谢

PS:我想过删除所有的迁移文件并重新运行它们,但由于这是一台生产服务器,我担心会丢失数据库内容或损坏一些东西。

find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete

所以Boris所描述的就是我遇到的问题。迁移文件中存在不一致,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。

迁移/操作/字段行中发现错误。不知何故,数据库和迁移文件之间出现了差异,或者您在迁移文件中应用了引用该字段的RunPython命令。

我也面临着类似的问题,在我的案例中,似乎是在两个旧的迁移文件中创建和删除了一个特定的字段,这似乎就是问题所在。

对你来说,解决方案是"修复"旧的迁移文件,或者压缩你的历史记录。

选项1(修复此错误需要查看所有迁移文件,并手动编辑此错误产生的迁移。如果您可以在调试模式下在本地编辑器中运行makemigration命令,则可以跟踪此错误发生的位置。遗憾的是,Django对这些错误的处理并没有那么详细。

选项2(一个更简单的选项,我会选择压缩迁移文件。因此,您可以删除迁移文件的所有历史记录,并将其简化为单个迁移步骤。请参阅文档。不利的一面是,您会丢失所有的历史记录,因此请确保您的本地、暂存和生产环境都已同步。特别是在生产方面,请确保数据库模型(如果使用postgres,则可以使用pgadmin(与代码中的Django模型完全相同。

压缩迁移文件实际上会删除整个历史记录。在您的示例中,如果您有一个迁移来添加字段price_per_hour,并且稍后将该字段重命名为price的迁移,则挤压将把这些迁移文件合并为一个操作,使字段price

最新更新