Django:迭代数据库视图的QuerySet

时间:2015-10-12 08:29:58

标签: django postgresql

我有一个Postgres数据库视图,它结合了其他表中的一些数据,我有一个Django模型来反映这个视图(针对这个问题进行了简化):

class MyModel(models.Model):
    othermodel = models.ForeignKey(MyOtherModel, related_name='cached_points')
    num_points = models.IntegerField(default=0)

    class Meta(object):
        managed = False

请注意 managed = False 语句,以确保Django不会尝试创建或更改表。

使用此模型一切正常,除了迭代它。当我这样做时,例如:

for item in MyModel.objects.all():
    ....

我得到以下异常:

  

django.db.utils.ProgrammingError:列app_mymodel.id不存在   第1行:SELECT" app_mymodel"。" id"," app_mymodel ...

我理解错误,因为确实没有专栏' id'在这个(虚拟)表中,但迭代器使用它来迭代结果。

如何在没有主键列的情况下迭代此QuerySet?

谢谢, 埃里克

3 个答案:

答案 0 :(得分:2)

Django requires each model to have one primary key

如果您没有指定primary_key,Django将添加一个id字段。在您的情况下,该字段不存在,因为模型未受管理,因此您会收到错误。

如果模型上有主键,您可以为该字段设置primary_key=True。如果other_model是唯一的,您可以使用它。

class MyModel(models.Model):
    othermodel = models.ForeignKey(MyOtherModel, primary_key=True, related_name='cached_points')
    ...

我不知道还有其他任何工作。

答案 1 :(得分:2)

我设法通过使用以下方法创建值的字典而不是访问模型字段来迭代结果:

items = MyModel.objects.all()
for item in items.values('field1', 'field2', ..):
    item['field1'] ...  # Access the data

我确定还有其他解决方案,但这对我的用例来说是最简单的。

感谢你指点我正确的方向,@ gbs& @Alasdair。

答案 2 :(得分:0)

解决方法是使用例如row_number()在视图中定义任意唯一ID字段,例如通过预先添加视图的查询,如下所示:

CREATE VIEW app_mymodel AS
SELECT row_number() OVER() as id, ...

我假设django会愉快地使用该id来迭代你的QuerySet。

BIG WARNING LABEL :这假定订购并不重要。任何尝试对QuerySets进行更复杂的处理(例如,对此id进行联合或联接)都将返回虚假结果,因为django无法将这些行分开。无论如何在数据库级别也是如此,因此如果您需要此功能,则应通过在ORDER BY子句中添加OVER指令来强制执行某种跨查询的一致排序。