Django 迁移错误:列不存在

Posted

技术标签:

【中文标题】Django 迁移错误:列不存在【英文标题】:Django Migration Error: Column does not exist 【发布时间】:2016-02-14 09:32:43 【问题描述】:

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

当然,这没有意义,因为当我尝试在迁移中创建该列时,该列显然不存在。

我在 Stack Overflow 上看到了很多关于这个 bug 的问题没有得到解答,或者有解决方案来手动创建迁移文件,或者销毁并重建数据库。这不是一个好的解决方案。

【问题讨论】:

【参考方案1】:

运行 makemigrations 后,请务必逐步查看堆栈跟踪。

在我的例子中,我注意到它通过调用包含在一个完全不同的应用程序中的 forms.py 中的表单来跟踪,而该应用程序恰好调用了我试图为其创建新迁移的模型。

将 Form 类从 forms.py 移到 views.py 中解决了这个问题。

【讨论】:

我遇到了同样的问题(Django 2.1.1),但只是注释掉了对表单中模型的调用。迁移运行后,再次取消注释。似乎有点错误 - 或者我们不应该从 forms.py 查询模型的原因是什么? 这个建议解决了我的问题。我在 forms.py 中调用了一个模型 (GeneralInfo),例如 stuff = list(set([(x.uw, x.uw) for x in models.GeneralInfo.objects.all()]))。此调用导致与 makemigrations 发生冲突【参考方案2】:

通过在 settings.py 中注释掉 INSTALLED_APPS 中的 django 调试工具栏为我解决了这个错误。我不确定为什么调试工具栏是罪魁祸首,但在我将其注释掉后,我能够毫无问题地运行 makemigrationsmigrate

希望这对某人有所帮助,因为我花了十二个小时试图弄清楚。

【讨论】:

这也发生在我身上,但不幸的是,我没有使用 Django 工具栏。不知道如何继续... 注释掉 Django 工具栏也对我有用。我的数据库是 SQLite。 过去的我,嘿嘿。再次遇到此问题,但您的修复无效(偶然发现很有趣)。你也应该和那个女孩分手。 2020 年见!【参考方案3】:

就我而言,那是因为我设置了 unique_together 约束。

当我想删除一个字段时,自动生成的迁移会在删除 unique_together 约束之前尝试删除该字段。

我必须做的是手动向上移动迁移文件中的 migrations.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)

在添加Boolean 字段后,我正在运行python manage.py makemigrations,如下所示:

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。之后,我取消了该行的注释,所有内容和表单的功能都和以前一样。

【讨论】:

这对我也有用。但我不确定为什么。我认为这与导入的顺序或设置中安装的应用程序的顺序有关。我试过先改变那些,但没有成功。 也许 Django ORM 查询是这里的问题 - 我正在考虑 ORM 调用 all() 方法的方式。我遇到了几乎完全相同的问题,但我的堆栈跟踪在Model.objects.all() 处显示了一个故障点。我没有在我的 forms.py 中使用此查询 - 这是在我的迁移文件中作为附加功能。 我可以确认该特定查询还有其他“怪癖”,尽管我不能很好地描述它们。只是当一切看起来都正确时它们会失败,并且像 name__in 这样的查询在该字段上不起作用。 是的,同样的情况。我浏览了错误跟踪并找出了我的代码的最后一个错误页面并注释了这些行,然后一切都很好【参考方案5】:

确保在加载应用程序时没有进行任何查询!,例如。在:

class A:
  field = fn_that_makes_query()

当运行migratemakemigrations 时,Django 执行系统检查,这会加载整个应用程序,因此如果在此过程中进行任何使用添加/更改的数据库字段的查询,您会遇到不一致,因为您正在尝试访问尚未存在的数据库文件。

【讨论】:

这是有道理的,但是怎么做呢?从阅读其他问题来看,似乎很多人需要使用 .all() 等 ORM 方法来填充表单选择等。如果您有任何文档或更好模式的示例,我们将不胜感激!【参考方案6】:

当我执行像 python manage.py makemigrations app1 这样的 cmd 时,我也遇到了同样的问题。 我通过评论在视图下的另一个 app2 中运行的自定义 orms 解决了我的问题。

例子:

在 app1 内 models.py

class ModelA(models.Model):
    subject = models.CharField(max_length=1)
    course = models.CharField(max_length=1)

在 app2 内 view.py

# obj = ModelA.object.all()
# get_subjct = [s.subject for s in obj]

所以在这里我已经注释了上面的代码并执行了 makemigrations 和 migrate 然后取消注释。

工作正常...

【讨论】:

【参考方案7】:

我遇到了同样的问题(列不存在)但是当我尝试运行 migrate 而不是 makemigrations

原因:在为最后一次更改运行迁移之前,我删除了迁移文件并用单个伪装的初始迁移文件 0001 替换了它们

解决办法:

    删除该应用迁移所涉及的表(如果有,请考虑备份解决方法) 从记录迁移的表 django_migrations 中删除负责迁移该应用程序的行,这是 Django 知道哪些迁移已应用以及哪些仍需要应用的方式。

这是解决这个问题的方法:

以 postgres 用户身份登录(我的用户名为 posgres):

sudo -i -u postgres

打开一个 sql 终端并连接到您的数据库:

psql -d database_name

列出您的表格并找出与该应用相关的表格:

\dt

删除它们(考虑与关系的删除顺序):

DROP TABLE tablename ;

列出迁移记录,您会看到应用的迁移分类如下:

标识 |应用 |姓名 |应用 --+--------+--------+---------+

SELECT * FROM django_migrations;

删除该应用程序的迁移行(您可以按 id 或按应用程序删除,应用程序不要忘记“引号”):

DELETE FROM django_migrations WHERE app='your_app';

退出并仅运行您的迁移(可能在您的情况下运行 makemigrations):

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

注意:在您的情况下,可能不必删除该应用程序的所有表,而不是所有迁移,只需删除导致问题的模型。

我希望这能有所帮助。

【讨论】:

【参考方案8】:

在我的 postgres 数据库迁移到不同的服务器后遇到这个问题。不知何故,我搞砸了数据库,无法使用新类 UserProfile 更新我的模型。

我解决了为现有架构创建初始迁移的问题:

    清空django_migrations 表:delete from django_migrations;使用命令DELETE FROM django_migrations WHERE app='my_app'; 对于每个应用,删除其migrations 文件夹:rm -rf <app>/migrations/ 重置“内置”应用程序的迁移:python manage.py migrate --fake 对于每个应用程序运行:python manage.py makemigrations <app>。注意依赖关系(具有 ForeignKey 的模型应该在其父模型之后运行)。 最后:python manage.py migrate --fake-initial

在这里得到它:https://***.com/a/29898483

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】:

我最近在升级到 Django 1.11 后遇到了这个问题。我想永久解决这个问题,这样我就不必每次在表上运行迁移时都注释/取消注释代码,所以我的方法:

from django.db.utils import ProgrammingError as AvoidDataMigrationError

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

我在导入过程中将异常重命名为 AvoidDataMigrationError,以便清楚为什么会出现。

【讨论】:

【参考方案10】:

当我尝试迁移 SingletonModel 以实际包含必要的字段时,刚刚出现了同样的错误。

错误的原因是我的模型 A 使用了此 SingletonModel 的某些字段(作为可配置值)。而且在迁移过程中模型 A 的实例化过程中,它显然不能保证我的迁移是安全的。

一位同事提出了一个绝妙的主意。将字段的默认值设为函数调用,因此是惰性的。

例子:

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

因此,我的建议是: 尝试使有问题的调用(在堆栈跟踪中看到)成为一个懒惰的调用。

【讨论】:

【参考方案11】:

我遇到了同样的问题,这是我的情况: 在应用程序MyApp 中,我向模型添加了一个新字段:

class Advisors(models.Model):
    AdvID = models.IntegerField(primary_key=True)
    Name = models.CharField(max_length=200,null=False)
    ParentID = models.IntegerField(null=True) # <--- the NEW field I add

所以我所做的是: 在MyProjecturls.py 中,而不是MyApp,注释掉链接到MyApp 的url(),然后执行makemigrationsmigrate 一切顺利; 在MyApp/urls.py 文件中:

urlpatterns = [
    url(r'^admin/', admin.site.urls, name='admin'),
    url(r'^$', views.HomePage.as_view(),name='home'),
    #comment out the following line, after migrate success, bring it back;
    # url(r'^myapp/', include('myapp.urls',namespace='research')), <--- 
]

【讨论】:

【参考方案12】:

聚会迟到了,但我想分享一些信息。这对我帮助很大! :)

我正在使用django-solo 将应用程序配置存储在数据库中,并且在向配置模型添加新字段时遇到了与 Alex 相同的问题。 Stacktrace 将我指向从数据库获取配置的行:conf = SiteConfiguration().get_solo()

在 Github 上有一个用于 django-solo 项目的 closed issue。这个想法是让模型加载变得懒惰(正如 MrKickkiller 之前指出的那样)。

所以对于现代 Django 版本(在我的例子中是 3.0),这段代码可以完美运行:

from django.utils.functional import SimpleLazyObject
conf = SimpleLazyObject(SiteConfiguration.get_solo)

【讨论】:

【参考方案13】:

最近陷入这个问题。

在我的例子中,我在代码中添加了对不存在字段的引用,然后我来到模型文件并添加了新字段,然后尝试运行 makemigrations 命令引发上述错误。

所以我一直到堆栈跟踪,发现新添加的引用是问题所在。将其注释掉,然后运行 ​​makemigrations 和瞧。

【讨论】:

【参考方案14】:

在我的情况下,这是因为我的自定义 AdminSite 在应用程序 start 上有 MyModel.objects.filter,我已为 makemigrationsmigrate 数据库禁用它。

【讨论】:

【参考方案15】:

我遇到了这个问题。要解决问题,请按照步骤操作。 1.打开数据库和表。 2.创建一个未退出的必需(有问题的sites_site.airport_codes)列 您的表具有默认值。

3.运行命令

python manage.py makemigrations

python manage.py migrate &lt;app name&gt;

python manage.py runserver

【讨论】:

【参考方案16】:

遇到了同样的问题,感谢这个帖子通过探索回溯为我指出了方向。

在 ListView 声明中,我声明了一个带有过滤器的查询集,该过滤器指向我尝试更新的模型,而没有覆盖 get_query_set() 函数。

    class BacklogListView(ListView):
        model = Version
        context_object_name = 'vhs'
        template_name = 'backlog_list.html'    
        queryset = VersionHistory.objects.filter(extract=Extract.objects.last())

修复者:

    class BacklogListView(ListView):
        model = Version
        context_object_name = 'vhs'
        template_name = 'backlog_list.html'
    
        def get_queryset(self):
            queryset = VersionHistory.objects.filter(extract=Extract.objects.last())

如果它可以帮助某人......

【讨论】:

【参考方案17】:

在修改数据库之前,您可能有一个使用模型的新状态的 RunPython,要解决这个问题,请始终使用 apps.get_model

def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    # if we directly import it, it'll be the wrong version
    SiteModel = apps.get_model('my_app', 'Site')

    # DONT
    from my_app.models import Site

def reverse_func(apps, schema_editor):
    ...

【讨论】:

【参考方案18】:

当您尝试在 Y 迁移之前将具有相关属性的应用 X 迁移到应用 Y 时会出现此问题。 p>

因此,要解决它,您必须首先进行 Y 的迁移。 您可以使用the django dependencies property

指定订单迁移

你也可以,运行:

python manage.py migrate --run-syncdb

然后对于每个导致应用程序的错误(如django.db.utils.ProgrammingError: relation "AppName_attribute" does not exist)run:

python manage.py migrate AppName

附注:

如果需要重置db schema,可以使用:

manage.py reset_schema

别忘了删除所有迁移文件:

find . | grep -E "(__pycache__|\.pyc|\.pyo$|migrations)" | xargs rm -rf

【讨论】:

【参考方案19】:

就我而言,我在迁移时遇到了错误。我使用以下步骤解决了这个问题。

makemigration 后创建的文件是。

# Example:
class Migration(migrations.Migration):

    dependencies = [
        ('app1', '0030_modify'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='users',
            name='phone1',
        ),
        migrations.RemoveField(
            model_name='users',
            name='phone2',
        ),
        migrations.AlterUniqueTogether(
            name='users',
            unique_together=('email', 'phone'),
        ),
        
    ]

我通过首先移动 unique_together 迁移,然后是字段移除解决了这个问题。

# Example:
class Migration(migrations.Migration):

    dependencies = [
        ('app1', '0030_modify'),
    ]

    operations = [
        migrations.AlterUniqueTogether(
            name='users',
            unique_together=('email', 'phone'),
        ),
        migrations.RemoveField(
            model_name='users',
            name='phone1',
        ),
        migrations.RemoveField(
            model_name='users',
            name='phone2',
        ),
    ]

希望它能解决你的问题

【讨论】:

以上是关于Django 迁移错误:列不存在的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 迁移显示现有列的列不存在

Django:DatabaseError 列不存在

即使在运行迁移后,Django Programming 错误列也不存在

Heroku:Django Migration 版本未在部署中运行

错误:“行/列不存在数据”使用 OdbcDataReader

SQL查询列不存在错误