不偷懒 Queryset 调用外部方法
Not lazy Queryset calls outside methods
我在工作中使用 Django,我仍在学习它的一些功能 - 最近我 运行 在我的一个视图中遇到了 Queryset 调用的问题。虽然代码 运行 非常适合我,但它在 CI 管道集上中断以从头开始初始化项目。
我得到的答案是因为对上述调用进行了非惰性评估——准确地说,它大致如下所示:
class MyListView(ListView):
queryset = (
MyModel.objects.all()
.exclude(some_type_field__in=[ContentType.objects.get_for_model(MyReferenceModel)])
.distinct()
)
template_name = #...
此外,我被告知不要编写未在方法之外延迟评估的 Queryset 调用 - 原因是 Python 解释器逐个模块执行代码。
但是我不明白这部分。方法与它有什么关系?如果上面的代码尝试实际访问数据库,为什么会出现问题?
为了进一步说明我的问题,我展示了我得到的解决方案:
class MyListView(ListView):
model = MyModel
def get_queryset(self):
return (
super()
.get_queryset()
.exclude(some_type_field__in=[ContentType.objects.get_for_model(MyReferenceModel)])
.distinct()
)
template_name = # ...
两者之间的实际区别是什么?我需要更好地理解这个问题,而 Django wiki 没有帮助。
不同之处在于,当您从此模块导入任何内容时,将执行模块和 class 级别的代码。
这就是 python 导入系统的工作方式,python 只是运行 .py
文件中的所有内容并将其放入全局模块“缓存”。
另一方面,除非调用,否则函数不会执行。唯一执行的是函数定义签名。即
def f(arg=[][0]):
return 1/0
导入时会给你 IndexError
。
你可以通过写文件来检查这个
# my_module.py
x = 4
print(x)
class A:
y = input("Hey, I'm blocking!")
def method(self):
return input("Hey, I'm not blocking unless called!")
然后从您的代码中尝试 from my_module import A
。
如果您在具有任何 i/o 的环境中工作 – 带有数据库的 Web 框架 – 这是常见的做法,在 import 中没有任何 i/o时间。通常,有一些机器可以帮助您解决这个问题。例如,在 django 中是 AppConfig
hooks.
我在工作中使用 Django,我仍在学习它的一些功能 - 最近我 运行 在我的一个视图中遇到了 Queryset 调用的问题。虽然代码 运行 非常适合我,但它在 CI 管道集上中断以从头开始初始化项目。
我得到的答案是因为对上述调用进行了非惰性评估——准确地说,它大致如下所示:
class MyListView(ListView):
queryset = (
MyModel.objects.all()
.exclude(some_type_field__in=[ContentType.objects.get_for_model(MyReferenceModel)])
.distinct()
)
template_name = #...
此外,我被告知不要编写未在方法之外延迟评估的 Queryset 调用 - 原因是 Python 解释器逐个模块执行代码。
但是我不明白这部分。方法与它有什么关系?如果上面的代码尝试实际访问数据库,为什么会出现问题?
为了进一步说明我的问题,我展示了我得到的解决方案:
class MyListView(ListView):
model = MyModel
def get_queryset(self):
return (
super()
.get_queryset()
.exclude(some_type_field__in=[ContentType.objects.get_for_model(MyReferenceModel)])
.distinct()
)
template_name = # ...
两者之间的实际区别是什么?我需要更好地理解这个问题,而 Django wiki 没有帮助。
不同之处在于,当您从此模块导入任何内容时,将执行模块和 class 级别的代码。
这就是 python 导入系统的工作方式,python 只是运行 .py
文件中的所有内容并将其放入全局模块“缓存”。
另一方面,除非调用,否则函数不会执行。唯一执行的是函数定义签名。即
def f(arg=[][0]):
return 1/0
导入时会给你 IndexError
。
你可以通过写文件来检查这个
# my_module.py
x = 4
print(x)
class A:
y = input("Hey, I'm blocking!")
def method(self):
return input("Hey, I'm not blocking unless called!")
然后从您的代码中尝试 from my_module import A
。
如果您在具有任何 i/o 的环境中工作 – 带有数据库的 Web 框架 – 这是常见的做法,在 import 中没有任何 i/o时间。通常,有一些机器可以帮助您解决这个问题。例如,在 django 中是 AppConfig
hooks.