我已经将一些指标事件导入到Django项目中。接下来,我将事件分组到Sessions中,Sessions被定义为给定时间窗口内的一系列连续事件。
我的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)我现在正在尝试非规范化这些会话的开始和结束时间,以避免必须对所有会话的事件进行最大和最小聚合。因此,我的新会话模型如下所示。
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)并且直接在DB模式中:
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进行的,以防有什么关系。
发布于 2014-02-17 06:49:57
请注意,您正在尝试使用join运行update语句--我非常确定SQLite不支持这一点;也就是说,它可能可以使用' with‘子句实现,但我怀疑Django是否能做到这一点(因为with-子句是在Django1.6之后很久才发布的版本3.8.3中才添加到SQLite中的)。我认为你得到了一些非常接近这个的东西:
$ 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)。
https://stackoverflow.com/questions/9537928
复制相似问题