【问题标题】:"no such column" error when running a data migration with django-south使用 django-south 运行数据迁移时出现“没有这样的列”错误
【发布时间】:2012-03-02 17:45:43
【问题描述】:

我已将一些指标事件导入 Django 项目。接下来,我将事件分组为会话,定义为给定时间窗口内的一系列连续事件。

我的 models.py 看起来像这样:

from django.db import models

from django.contrib.auth.models import User

class Event(models.Model):
    name = models.CharField(max_length=255, blank=True, db_index=True)
    id1 = models.CharField(max_length=255, blank=True, db_index=True)
    id2 = models.CharField(max_length=255, blank=True)
    time = models.DateTimeField(db_index=True)
    user = models.ForeignKey(User, related_name='events', null=True, db_index=True)
    session = models.ForeignKey('Session', related_name='events', null=True, db_index=True)
    def __unicode__(self):
        return '"%s" event' % self.name or 'unnamed'

class Session(models.Model):
    user = models.ForeignKey(User, related_name='sessions', null=True)

我现在正尝试对这些会话的开始和结束时间进行非规范化,以避免对所有会话的事件进行 MAX 和 MIN 聚合。所以我的新 Session 模型看起来像这样。

class Session(models.Model):
    user = models.ForeignKey(User, related_name='sessions', null=True)
    start = models.DateTimeField(db_index=True, null=True)
    end = models.DateTimeField(db_index=True, null=True)

我已经添加了字段,创建了架构迁移(运行良好)并创建了数据迁移:

import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models

class Migration(DataMigration):

    def forwards(self, orm):
        "Write your forwards methods here."
        orm.Session.objects  \
            .annotate(
                start_time=models.Min('events__time'),
                end_time=models.Max('events__time'))  \
            .update(start=models.F('start_time'), end=models.F('end_time'))

    def backwards(self, orm):
        "Write your backwards methods here."
        pass


    models = {
        'auth.group': {

...

    'metrics_import.event': {
        'Meta': {'object_name': 'Event'},
        'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
        'id1': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
        'id2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
        'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
        'session': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'events'", 'null': 'True', 'to': "orm['metrics_import.Session']"}),
        'time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
        'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'events'", 'null': 'True', 'to': "orm['auth.User']"})
    },
    'metrics_import.session': {
        'Meta': {'object_name': 'Session'},
        'end': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
        'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
        'start': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
        'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sessions'", 'null': 'True', 'to': "orm['auth.User']"})
    }
}

看起来很简单,但是运行数据迁移会给出:

django.db.utils.DatabaseError: no such column: metrics_import_event.time

我已经从 django shell 检查了该列确实存在:

>>> Event.objects.all()[0].time
datetime.datetime(2012, 1, 19, 3, 0, 3)

直接在数据库模式中:

sqlite> .schema metrics_import_event
CREATE TABLE "metrics_import_event" (
    "id" integer NOT NULL PRIMARY KEY,
    "name" varchar(255) NOT NULL,
    "id1" varchar(255) NOT NULL,
    "id2" varchar(255) NOT NULL,
    "time" datetime NOT NULL,
    "user_id" integer REFERENCES "auth_user" ("id"),
    "session_id" integer
);
CREATE INDEX "metrics_import_event_3a04cc98" ON "metrics_import_event" ("time");
CREATE INDEX "metrics_import_event_52094d6e" ON "metrics_import_event" ("name");
CREATE INDEX "metrics_import_event_6b4dc4c3" ON "metrics_import_event" ("session_id");
CREATE INDEX "metrics_import_event_fbfc09f1" ON "metrics_import_event" ("user_id");

我确定我错过了一些愚蠢的东西,但不知道是什么。

谢谢!

编辑:请注意,初始架构迁移是使用--fake 应用的,以防万一。

【问题讨论】:

  • 您说您之前运行过 --fake 迁移 -- 您列出的示例来自运行最终迁移之前?
  • @Alvin 是的,我使用 --fake 运行了初始迁移,因为我已经使用 syncdb 创建了初始表。我显示的 SQL 输出是在运行迁移之前(它无法运行,因为它失败了——因此问题:)
  • 您是否尝试过运行分析器来查看正在生成的查询是什么?想知道时间列是否包含在 time 中以避免碰到保留字?

标签: django data-migration django-south


【解决方案1】:

请注意,您正在尝试使用连接运行更新语句——我很确定这不受 Sqlite 支持;也就是说,它可能可以使用'with'子句来实现,但我怀疑 Django 是否这样做(因为 with 子句仅在 3.8.3 版本中添加到 SQLite,在 Django 1.6 之后很久才发布)。我认为你得到的东西非常接近这个:

$ sqlite3 
SQLite version 3.8.3.1 2014-02-11 14:52:19
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table x (a int, b int);
sqlite> insert into x values(1,2);
sqlite> select * from x;
1|2
sqlite> create table y (c int, d int);
sqlite> update x set b = min (y.d);
Error: no such column: y.d

我认为您可以设置日志记录以在执行之前打印所有 SQL,这样您可以获得更多信息。

(这个答案猜测,实际上,这与 South 无关——问题出在 Django 中)。

【讨论】:

    猜你喜欢
    • 2017-12-10
    • 2011-08-06
    • 1970-01-01
    • 2012-08-06
    • 2011-09-28
    • 1970-01-01
    • 2015-12-07
    • 2020-04-15
    • 2017-06-28
    相关资源
    最近更新 更多