【问题标题】:Django how to query objects one by oneDjango如何一一查询对象
【发布时间】:2018-03-22 01:06:10
【问题描述】:

我必须从模型中查询一个对象,这个对象被称为“练习”并且有很多字段(标题、正文、答案等)我需要一个一个地获取“练习对象”及其所有字段,对它们进行一些渲染并返回练习的 pdf 作为结果。

问题是,如果我这样做:

exercises = ExerciseModel.objects.all()

我得到了所有这些。如果我这样做:

some_exercises = ExerciseModel.objects.filter(something=something)

我得到“其中一些”取决于过滤器。如果我这样做:

 exercise = ExerciseModel.objects.get()

我明白了

错误 get() 返回了不止一个练习

如何才能一一获取?我必须能够将它们用作另一个函数的输入。

【问题讨论】:

  • 为什么不能遍历“all”或“some”?
  • 因为有30.000个练习,我不能每次都返回30000个pdf,所以我必须得到一个任意练习并且只对其进行操作
  • 要获得单个实例,您需要将一些条件(例如主键)实际传递给get()

标签: python django django-queryset


【解决方案1】:

如果您只需要在 1 个练习中执行任务,请改用 get()。在这种情况下,您需要一个标准来确保 get() 将返回 1 且仅返回 1 个结果。

例子:

ex = ExerciseModel.objects.get(pk=123)

来自doc

返回与给定查找参数匹配的对象,该参数应采用字段查找中描述的格式。

get() 如果发现多个对象,则引发 MultipleObjectsReturnedMultipleObjectsReturned 异常是模型类的一个属性。

get() 如果未找到给定参数的对象,则会引发 DoesNotExist 异常。这个异常是模型类的一个属性。

当您有一个带有过滤器的 QuerySet 以确保基础 SQL 请求将仅返回 1 行时,您可以在 QuerySet 上不带参数调用 get()。这会将行作为模型实例返回,而不是作为包含 1 个元素的列表返回。

原答案:

filter()all() 方法都返回一个 QuerySet 实例。您可以对其进行迭代,为您的请求返回的每个“练习”执行一项任务

for exercise in ExerciseModel.objects.filter(something=something):
    # ... do what you need on your exercise

来自documentation

QuerySet 是可迭代的,它会在您第一次迭代时执行其数据库查询。例如,这将打印数据库中所有条目的标题

【讨论】:

    【解决方案2】:

    你需要的是.iterator(),它将一个查询集变成一个迭代器:

    exercises = ExerciseModel.objects.all().iterator()
    

    然后你在 for 循环中迭代它:

    for exercise in exercises:
        ...
    

    当您拥有大量项目时,这将提高性能。但是,它也有一些缺点,正如docs

    中所述

    希望对你有帮助!

    【讨论】:

    • 首先感谢您的帮助,我已经尝试过这种方式,但效果不佳,因为我有一个包含 30k+ 练习的“池”,我必须进行一项任意练习,而不是全部练习一个一个,我的错,可能问题不是很清楚
    • 不是专家,但应该是:for exercise in ExerciseModel.objects.iterator(chunk_size=100): ... 它将在所有对象上创建一个迭代器,但同时只有 100 个对象会在内存中......
    【解决方案3】:

    .get() 必须返回单个对象,而不是 QuerySet 实例。如果您想进行一次练习,则必须将参数传递给.get 实例。例如,按名称检索对象将需要以下代码:

    exercise = ExerciseModel.objects.get(name="an_exercise")

    如果您想遍历所有对象而不实际检索包含对象的 QuerySet,您可以使用以下代码:

    for i in range(Exercise.objects.all().count()):
        exercise = Exercise.objects.get(pk=i)
        ... operate on object ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      • 1970-01-01
      • 2016-06-21
      • 2011-02-19
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多