【问题标题】:Django: Iterate over QuerySet of a database viewDjango:遍历数据库视图的 QuerySet
【发布时间】:2016-01-09 15:50:50
【问题描述】:

我有一个 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 行:选择 "app_mymodel"."id", "app_mymodel...

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

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

谢谢, 埃里克

【问题讨论】:

    标签: django postgresql


    【解决方案1】:

    姜戈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')
        ...
    

    我不知道有任何其他解决方法。

    【讨论】:

      【解决方案2】:

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

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

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

      感谢@gbs 和@Alasdair 为我指明了正确的方向。

      【讨论】:

        【解决方案3】:

        一种解决方法是在您的视图中定义一个任意唯一的 id 字段,例如使用 row_number(),例如通过预先像这样的视图查询:

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

        我认为 django 会很乐意使用该 id 来迭代您的 QuerySet。

        大警告标签:假设排序并不重要。任何对 QuerySet 进行更复杂处理的尝试(例如,此 id 上的联合或联接)都将返回虚假结果,因为 django 将无法区分行。无论如何,这在数据库级别也是如此,因此如果您需要此功能,那么您应该通过在 OVER 子句中添加 ORDER BY 指令来强制执行某种一致的查询排序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-08
          • 2015-01-16
          • 2018-03-06
          • 1970-01-01
          • 2013-06-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多