代码之家  ›  专栏  ›  技术社区  ›  Wagh

在django中计算QuerySets时难以理解

  •  4
  • Wagh  · 技术社区  · 9 年前

    考虑以下示例

    data = Employee.objects.all()
    for i in data:
       print i.name
    

    根据我在这里的理解,每个循环都会命中数据库。我不确定我是对还是错。

    下一个疑问是

    data = Employee.objects.get(id=1)
    

    在这种情况下,它何时会访问数据库?如果我将数据存储到另一个变量中呢?

    如果我做了呢

    data = Employee.objects.all()
    data1 = []
    data1 = data
    for i in data1:
        print i
    

    上面和这个有什么区别?

    2 回复  |  直到 9 年前
        1
  •  9
  •   Alex Morozov    9 年前
    1. 在第一种情况下,对查询集进行求值(并因此命中数据库) once -在循环开始时。
    2. 这个 get() 调用将立即进入数据库。所有模型数据都将被提取,访问模型属性时不会碰到数据库(除非它们是 ForeignKeys ). 如果已将其存储在另一个变量中,则这些实例不会以任何方式链接。例如:

      var1 = Employee.objects.get(pk=1)
      var2 = Employee.objects.get(pk=1)
      
      var1.name = 'var1'
      var2.name = 'var2'
      var2.save()
      
      print var1.name
      >>> 'var1'
      

    如果您想获取保存的对象的最新版本,可以调用 refresh_from_db() 方法

        var1.refresh_from_db()
        var1.name
        >>> 'var2'
    
    1. 1)和3)之间没有区别,因为在3)中,您只需通过 data1 变量它不会在赋值时求值,而是在迭代时求值。
        2
  •  3
  •   doru    9 年前
    1. 在第一种情况下,它将在for循环开始时命中数据库,更准确地说是在第一个循环中。

    2. 在第二种情况下,它还没有到达数据库,因为QuerySet尚未计算。QuerySet是惰性的,在以下情况下进行计算:

    • 第一次迭代它们
    • 当你切它们的时候。例如: Post.objects.all()[:3]
    • 当你腌制或缓存它们时
    • 当你打电话时 repr() len() 在他们身上
    • 当您显式调用 list() 在他们身上
    • 当您在诸如 bool() , or , and if

    从书中 Django by Example, p. 21

    有关何时计算QuerySet的详细信息,请参见 docs .