(这是一个老问题,但仍然绊倒人了,仍然是高度相关的,以使用Django与预先存在的,规范化模式任何一个区域。)
在你的SELECT语句,你需要添加一个数字“ID”,因为Django需要一个,即使在非托管模型上。如果在行的某个地方没有保证唯一的整数值(通常是这种情况),则可以使用row_number()窗口函数来完成此操作。
在这种情况下,我使用ORDER BY子句与窗口函数,但你可以做任何有效的事情,而当你在它的时候,你可能会使用一个对你有用的子句。只要确保你不要尝试使用Django的ORM点引用关系,因为它们默认查找“id”列,而你的是假的。
此外,我会考虑重命名我的输出列更有意义的东西,如果你打算在一个对象内使用它。有了这些变化的查询看起来更像是(当然,替换你自己的条件为“AS”条款):
CREATE VIEW qry_desc_char as
SELECT
row_number() OVER (ORDER BY tbl_char.cid) AS id,
tbl_desc.iid_id AS iid_id,
tbl_desc.cid_id AS cid_id,
tbl_desc.cs AS a_better_name,
tbl_char.cid AS something_descriptive,
tbl_char.charname AS name
FROM tbl_desc,tbl_char
WHERE tbl_desc.cid_id = tbl_char.cid;
一旦做到这一点,在Django模型看起来是这样的:
class QryDescChar(models.Model):
iid_id = models.ForeignKey('WhateverIidIs', related_name='+',
db_column='iid_id', on_delete=models.DO_NOTHING)
cid_id = models.ForeignKey('WhateverCidIs', related_name='+',
db_column='cid_id', on_delete=models.DO_NOTHING)
a_better_name = models.CharField(max_length=10)
something_descriptive = models.IntegerField()
name = models.CharField(max_length=50)
class Meta:
managed = False
db_table = 'qry_desc_char'
您不需要id列名称末尾的“_id”部分,因为您可以使用“db_column”参数更具描述性地在Django模型中声明列名称,如上所述但在这里我只是为了防止Django将的另一个“_id”添加到cid_id和iid_id的末尾 - 它添加了零语义值赞同你的代码)。另外,请注意“on_delete”参数。在涉及级联删除时,Django自己做了一件事,而在一个您不想要的有趣数据模型上 - 当涉及到视图时,您只会遇到错误和异常终止的事务。在Django 1.5之前,你必须对它进行修补才能使DO_NOTHING实际上意味着“什么也不做” - 否则在经历它的删除循环之前,它仍然会尝试(不必要地)查询和收集所有相关的对象,并且查询将失败,整个操作。
顺便提一句,I wrote an in-depth explanation of how to do this只是有一天。