如何从 postgresql 视图表中获取要显示的对象列表
Posted
技术标签:
【中文标题】如何从 postgresql 视图表中获取要显示的对象列表【英文标题】:How can i get a list of objects from a postgresql view table to display 【发布时间】:2010-12-12 11:05:15 【问题描述】:这是视图表的模型。
class QryDescChar(models.Model):
iid_id = models.IntegerField()
cid_id = models.IntegerField()
cs = models.CharField(max_length=10)
cid = models.IntegerField()
charname = models.CharField(max_length=50)
class Meta:
db_table = u'qry_desc_char'
这是我用来创建表的 SQL
CREATE VIEW qry_desc_char as
SELECT
tbl_desc.iid_id,
tbl_desc.cid_id,
tbl_desc.cs,
tbl_char.cid,
tbl_char.charname
FROM tbl_desC,tbl_char
WHERE tbl_desc.cid_id = tbl_char.cid;
我不知道我是否需要模型或视图中的功能或两者兼而有之。我想从该数据库中获取对象列表以显示它。这可能很容易,但我是 Django 和 python 的新手,所以我遇到了一些问题
【问题讨论】:
【参考方案1】:您正在尝试从视图中获取记录。这是不正确的,因为视图不映射到模型,表映射到模型。
您应该使用 Django ORM 来获取 QryDescChar
对象。请注意,Django ORM 将直接从表中获取它们。您可以查阅 Django 文档以了解 extra()
和 select_related()
方法,这将允许您以不同的方式获取相关数据(您想从另一个表中获取的数据)。
【讨论】:
【参考方案2】:如果您的 RDBMS 允许您创建可写视图,并且您创建的视图具有与 Django 创建的表完全相同的结构,我想这应该可以直接工作。
【讨论】:
【参考方案3】:Django 1.1 引入了一个您可能会觉得有用的新功能。您应该能够执行以下操作:
class QryDescChar(models.Model):
iid_id = models.IntegerField()
cid_id = models.IntegerField()
cs = models.CharField(max_length=10)
cid = models.IntegerField()
charname = models.CharField(max_length=50)
class Meta:
db_table = u'qry_desc_char'
managed = False
托管元类选项的文档是here。相关引述:
如果为 False,则不创建数据库表 或删除操作将 为此模型执行。这是 如果模型代表一个 现有表或数据库视图 是通过其他方式创建的。 这是唯一的区别 管理为 False。的所有其他方面 模型处理与 正常。
完成后,您应该可以正常使用您的模型了。要获取对象列表,您可以执行以下操作:
qry_desc_char_list = QryDescChar.objects.all()
要真正将列表放入模板中,您可能需要查看通用视图,特别是 object_list 视图。
【讨论】:
【参考方案4】:(这是一个古老的问题,但仍然是一个令人困惑的领域,并且仍然与使用预先存在的规范化模式的 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 只是前几天。
【讨论】:
以上是关于如何从 postgresql 视图表中获取要显示的对象列表的主要内容,如果未能解决你的问题,请参考以下文章