Django在迁移到1.2.5后测试失败 - 子模型的主键问题

问题描述:

我有一个从模型Object继承的模型ThreadedComment。 ThreadedComment没有自己的唯一主键,依赖于Object的主键(“ID”)。这是该模型是如何构建的:Django在迁移到1.2.5后测试失败 - 子模型的主键问题

class Object(models.Model): 
    permalink = models.CharField(max_length=128) 
    status = models.IntegerField() 
    version = models.IntegerField() 

class ThreadedComment(Object): 
    parent = models.ForeignKey('self', null=True, blank=True, default=None, related_name='children') 
    parent_object = models.OneToOneField(Object, parent_link=True) 
    # other fields follow 

这很好工作,直到Django的1.2.3,但是当我升级到1.2.5的Django(1.3有同样的问题),这种情况发生的时候我试图运行任何测试:

Error: Database test_db couldn't be flushed. Possible reasons: 
    * The database isn't running or isn't configured correctly. 
    * At least one of the expected database tables doesn't exist. 
    * The SQL was invalid. 
Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. 
The full error: relation "threadedcomments_threadedcomment_id_seq" does not exist 
LINE 1: SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1... 

问题是用“sqlflush”命令生成并执行SQL文件。有问题的行是:

SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false); 

这显然失败,因为该表中没有“id”列。

什么是野趣,Django的1.2.3版本产生相似的输出:

SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false); 

但测试的推移反正所以我没有注意到之前的问题。

我在这里做错了什么?模型定义是否不正确,即,我是否需要在线索评论中有一个主键,即使我不需要它与对象具有一对一的关系?那么它是如何从1.0到1.1一直工作到1.2.3,现在又在1.2.5中突破的呢?

这原来是一个django错误。详情点击此处:http://code.djangoproject.com/ticket/12728

这里是我们的临时解决方法:https://bitbucket.org/filmaster/filmaster-test/changeset/afbac905cf63

+0

+1良好的工作跟踪下来。 – 2011-04-19 22:26:25

+0

这似乎仍然是Django 1.4.3的一个开放的bug。 – Erik 2013-01-03 05:15:10

我不能在trunk或1.2.3上重现它;我创建了应用程序“threadedcomments”和车型新项目,你贴有以下结果:

BEGIN; 
TRUNCATE "threadedcomments_threadedcomment", "auth_permission", "auth_group", "auth_group_permissions", "django_session", "auth_user_groups", "auth_user_user_permissions", "threadedcomments_object", "auth_message", "django_site", "auth_user", "django_content_type"; 
SELECT setval(pg_get_serial_sequence('"auth_permission"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"auth_group"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"auth_user"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"auth_message"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"django_content_type"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"django_site"','id'), 1, false); 
SELECT setval(pg_get_serial_sequence('"threadedcomments_object"','id'), 1, false); 
COMMIT; 

序列threadedcomments_threadedcomment_id_seq,从未创建和Django不尝试刷新它。我不认为这是一个版本变化相关的错误(而是一直存在的东西,但没有被注意到)。

+0

它适用于1.2.3。它在1.2.5和1.3上失败(至少那些是我测试的版本)。此外,请不要在threadedcomments应用程序中对其进行测试,而只需创建一个类似我所描述的模型。我们正在Filmaster上使用大量黑客入侵的threadcomments应用程序。另一种复制方式:只需从hg clone https://bitbucket.org/filmaster/filmaster-reloaded获取源代码,然后在1.2.3和1.2.5上运行python manage.py sqlflush来查看我的意思。 – michuk 2011-04-06 00:10:48

你说:“ThreadedComment没有自己的唯一主键,依赖于Object的promary [原文]键('ID')。” Django需要将一个字段标识为主键。请参阅Automatic primary key fields

更多细节。 。 。

函数pg_get_serial_sequence()返回特定列使用的序列的名称。因此,以下语句表示“获取表'threadedcomments_threadedcomment'中'id'列所用序列的名称,将序列的last_value字段设置为1,并在nextval()被调用时返回1.

SELECT setval(pg_get_serial_sequence('"threadedcomments_threadedcomment"','id'), 1, false); 

但这句话

SELECT setval('"threadedcomments_threadedcomment_id_seq"', 1, false); 

手段 “将名为 'threadedcomments_threadedcomment_id_seq' 1序列的LAST_VALUE领域,并在下次返回1 NEXTVAL()被调用。”

我的猜测是Django用来命名se的算法版本之间会发生变化。我见过其他系统进行类似的更改,因为通过连接表名和列名建立的标识符变得太长了。我认为Oracle标识符有30个字符的限制;您的标识符是39个字符。我见过Rails生成70多个字符标识符,它们在PostgreSQL上打破(63或64个字符限制)。

+0

“Django需要将一个字段标识为主键” - 是的,我知道这一点,但它用于在父表中的ID而不是子表中正常工作。因为这里的关系是一对一的,所以在子表中复制ID没有任何意义。 我应该创建一个只有满足django的primary_key = True的fake_id字段吗?这听起来像一个可怕的解决方法。 – michuk 2011-04-07 20:37:38

+0

我想说你可能只需要在parent_object上设置'primary_key = True'。从我发布的链接中,“OneToOneField类用于自动成为模型的主键,这不再是真实的(尽管如果你喜欢,你可以手动传递primary_key参数)”。 – 2011-04-07 21:27:27

+0

父对象已经有了primary_key = True。这原来是一个django错误。更多的细节在我自己的答案下面这个问题。 – michuk 2011-04-19 18:09:43