(这是一个古老的问题,但仍然是一个令人困惑的领域,并且仍然与使用预先存在的规范化模式的 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 在 cid_id 和 iid_id 的末尾添加 another "_id" - 这为您的代码添加了零语义值)。另外,请注意“on_delete”参数。当涉及到级联删除时,Django 会做自己的事情,而在一个有趣的数据模型上你不希望这样做——当涉及到视图时,你只会得到一个错误和一个中止的事务。在 Django 1.5 之前,您必须对其进行修补以使 DO_NOTHING 实际上意味着“什么都不做”——否则它仍然会尝试(不必要地)在执行删除周期之前查询并收集所有相关对象,并且查询将失败,停止整个操作。
顺便说一句,I wrote an in-depth explanation of how to do this 只是前几天。