Django迁移错误:列不存在

时间:2015-11-12 21:39:49

标签: django postgresql python-3.x django-models

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上这个没有答案的错误的问题,或者有一个解决方案来手动创建迁移文件,或者销毁和重建数据库。这不是一个好的解决方案。

19 个答案:

答案 0 :(得分:10)

运行makemigrations后,请务必逐步完成堆栈跟踪。

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

将Forms类从forms.py移到views.py中修复了问题。

答案 1 :(得分:7)

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

希望这有助于某人,因为我花了12个小时试图解决这个问题。

答案 2 :(得分:5)

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

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

我必须做的是手动向上移动迁移文件中的migrations.AlterUniqueTogether约束,以便django在尝试删除字段之前首先删除约束。

我希望这可以帮助别人。

答案 3 :(得分:3)

执行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并进行了迁移,然后对其进行了注释。

工作正常...

答案 4 :(得分:2)

我也遇到了这个问题,@ 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的建议,我逐行经历了stacktrace,假设这不是Django的核心问题。事实证明,在一个应用forms.py文件中,我具有以下内容:

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

解决方案是简单地注释掉该行,运行manage.py makemigrations,然后运行manage.py migrate。之后,我取消注释该行,所有内容和表单的功能都像以前一样工作。

答案 5 :(得分:1)

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

class A:
  field = fn_that_makes_query()

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

答案 6 :(得分:1)

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

我正在使用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)

答案 7 :(得分:1)

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

from django.db.utils import ProgrammingError as AvoidDataMigrationError

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

我在导入期间将异常重命名为AvoidDataMigrationError,因此很清楚为什么存在该异常。

答案 8 :(得分:0)

现在,当我尝试将SingletonModel迁移为实际上包含必要字段时,也遇到了相同的错误。

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

一个同事有一个绝妙的主意。将字段的默认值设为函数调用,因此很懒。

示例:

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

因此,我的建议是:     尝试使有问题的调用(在stacktrace中可见)成为一个懒惰的调用。

答案 9 :(得分:0)

最近陷入这个问题。

对于我来说,我在代码中添加了对不存在字段的引用,然后进入模型文件并添加了新字段,然后尝试运行the main.bunble.js命令,该命令引发了以上错误。

所以我一直走到堆栈跟踪,发现新添加的引用是问题所在。对此进行了评论,然后运行makemigrations,瞧瞧。

答案 10 :(得分:0)

在我的情况下,由于我的自定义AdminSite在应用程序MyModel.objects.filter上有start,所以发生了这种情况,我已为makemigrationsmigrate数据库禁用了它。 / p>

答案 11 :(得分:0)

我遇到了同样的问题,这是我的情况: 在应用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

所以我做的是: 在urls.py的{​​{1}}中,而不是MyProject中,注释掉链接到MyApp的url(),然后执行MyAppmakemigrations好; 在migrate文件中:

MyApp/urls.py

答案 12 :(得分:0)

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

  • 原因:我删除了迁移文件,并在运行上次更改的迁移之前将其替换为单个假装初始迁移文件0001

  • 解决方案:

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

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

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

    sudo -i -u postgres

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

    psql -d database_name

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

    \dt

  • 放弃它们(考虑关系下降顺序):

    DROP TABLE tablename ;

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

id | app |名字|应用
   - + ------ + -------- + --------- +

SELECT * FROM django_migrations;
  • 删除该应用的迁移行(您可以按ID或应用删除,应用不要忘记&#39;报价&#39;):

    DELETE FROM django_migrations WHERE app='your_app';

  • 仅注销并运行您的迁移(可能在您的情况下运行makemigrations):

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

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

我希望这可以提供帮助。

答案 13 :(得分:0)

我遇到了这个问题。解决问题的步骤。
1.打开数据库和表。
2.创建一个必需的(sites_site.airport_codes)列,该列不在 您的表格具有默认值。

3。运行命令

python manage.py makemigrations

python manage.py migrate <app name>

python manage.py runserver

答案 14 :(得分:0)

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

在 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())

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

答案 15 :(得分:0)

在修改数据库之前,您可能有一个使用所需模型新状态的 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):
    ...

答案 16 :(得分:0)

当您尝试在 Y 迁移之前迁移与应用 Y 具有相关属性的应用 X 时,会发生此问题。 >

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

指定订单迁移

你也可以运行:

static String getSuperClassNameOf(ClassLoader loader, String className)
    throws ClassNotFoundException, IOException {

    String resName = className.replace('.', '/') + ".class";
    InputStream is;
    getStream: {
        for(; loader != null; loader = loader.getParent()) {
            is = loader.getResourceAsStream(resName);
            if(is != null) break getStream;
        }
        is = ClassLoader.getSystemResourceAsStream(resName);
    }
    if(is == null) throw new ClassNotFoundException(className);
    className = getSuperClassName(ByteBuffer.wrap(is.readAllBytes()));
    return className.replace('/', '.');
}

static String getSuperClassName(ByteBuffer buf) {
    if(buf.order(ByteOrder.BIG_ENDIAN).getInt()!=0xCAFEBABE) {
        throw new IllegalArgumentException("not a valid class file");
    }
    int minor=buf.getChar(), ver=buf.getChar(), poolSize=buf.getChar();
    int[] pool = new int[poolSize];
    //System.out.println("version "+ver+'.'+minor);
    for(int ix=1; ix<poolSize; ix++) {
        String s; int index1=-1, index2=-1;
        byte tag = buf.get();
        switch(tag) {
            default: throw new UnsupportedOperationException(
                    "unknown pool item type "+buf.get(buf.position()-1));
            case CONSTANT_Utf8:
                buf.position((pool[ix]=buf.position())+buf.getChar()+2); continue;
            case CONSTANT_Module: case CONSTANT_Package: case CONSTANT_Class:
            case CONSTANT_String: case CONSTANT_MethodType:
                pool[ix]=buf.getChar(); break;
            case CONSTANT_FieldRef: case CONSTANT_MethodRef:
            case CONSTANT_InterfaceMethodRef: case CONSTANT_NameAndType:
            case CONSTANT_InvokeDynamic: case CONSTANT_Dynamic:
            case CONSTANT_Integer: case CONSTANT_Float:
                buf.position(buf.position()+4); break;
            case CONSTANT_Double: case CONSTANT_Long:
                buf.position(buf.position()+8); ix++; break;
            case CONSTANT_MethodHandle: buf.position(buf.position()+3); break;
        }
    }
    int access = buf.getChar(), thisClass = buf.getChar(), superClass = buf.getChar();
    buf.position(pool[pool[superClass]]);
    return decodeString(buf);
}
private static String decodeString(ByteBuffer buf) {
    int size=buf.getChar(), oldLimit=buf.limit();
    buf.limit(buf.position()+size);
    StringBuilder sb=new StringBuilder(size+(size>>1));
    while(buf.hasRemaining()) {
        byte b=buf.get();
        if(b>0) sb.append((char)b);
        else {
            int b2 = buf.get();
            if((b&0xf0)!=0xe0)
                sb.append((char)((b&0x1F)<<6 | b2&0x3F));
            else {
                int b3 = buf.get();
                sb.append((char)((b&0x0F)<<12 | (b2&0x3F)<<6 | b3&0x3F));
            }
        }
    }
    buf.limit(oldLimit);
    return sb.toString();
}
private static final byte CONSTANT_Utf8 = 1, CONSTANT_Integer = 3,
    CONSTANT_Float = 4, CONSTANT_Long = 5, CONSTANT_Double = 6,
    CONSTANT_Class = 7, CONSTANT_String = 8, CONSTANT_FieldRef = 9,
    CONSTANT_MethodRef = 10, CONSTANT_InterfaceMethodRef = 11,
    CONSTANT_NameAndType = 12, CONSTANT_MethodHandle = 15,
    CONSTANT_MethodType = 16, CONSTANT_Dynamic = 17, CONSTANT_InvokeDynamic = 18,
    CONSTANT_Module = 19, CONSTANT_Package = 20;

然后对于每个错误导致的应用程序(例如 python manage.py migrate --run-syncdb run:

django.db.utils.ProgrammingError: relation "AppName_attribute" does not exist)

附注:

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

python manage.py migrate AppName

并且不要忘记删除所有迁移文件:

manage.py reset_schema

答案 17 :(得分:0)

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

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',
        ),
    ]

希望它能解决您的问题

答案 18 :(得分:-1)

将postgres数据库迁移到不同的服务器后遇到此问题。不知何故,我弄乱了数据库,无法使用新类UserProfile更新我的模型。

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

  1. 使用命令django_migrations
  2. 清空delete from django_migrations;表:DELETE FROM django_migrations WHERE app='my_app';
  3. 对于每个应用,请删除其migrations文件夹:rm -rf <app>/migrations/
  4. 重置“内置”应用的迁移:python manage.py migrate --fake
  5. 对于每个应用运行:python manage.py makemigrations <app>。处理依赖关系(具有ForeignKey的模型应该在其父模型之后运行)。
  6. 最后:python manage.py migrate --fake-initial
  7. 点击此处:https://stackoverflow.com/a/29898483

    PS我不确定这是否与解决问题有关,但首先,我在postgresql中删除了导致错误的表,并在模型中注释掉了UserProfile类。

    shell中的

     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)