可以在 Django 视图中使用 Python 生成器吗?
Posted
技术标签:
【中文标题】可以在 Django 视图中使用 Python 生成器吗?【英文标题】:Can Python Generators be used in Django Views? 【发布时间】:2015-01-23 01:14:08 【问题描述】:问题:
基本上我想在每次调用视图时从数据库中返回一个唯一的结果(直到我用完唯一的对象并不得不重新开始)。我在想一个简单而优雅的解决方案是使用生成器来处理这个问题。这是可能的吗?如果可以,如何从 ORM 中提取值?
注意:
我认为会话或使用像 Memento 这样的设计模式可能是一个解决方案,但我真的很想知道 Python 生成器是否以及如何在这种情况下使用。
【问题讨论】:
这完全取决于您期望如何使用它们。请记住,在正常生产中,您有多个进程正在运行。这使得难以维持全局状态。你可能想看看使用缓存来做这种事情。 【参考方案1】:由于 Django 是同步 wsgi,您必须单独处理每个请求,您的 python 环境可以随时终止或切换到另一个环境。
如果你没有恐惧和单一进程,你可以创建一个文件范围字典,其中包含每次都会使用的会话 ID 和迭代器
from django.shortcuts import render
from collections import defaultdict
import uuid
def iterator():
for item in DatabaseTable.objects.all():
yield item
sessions_current_iterators = defaultdict(iterator)
def my_view(request):
id = request.session.get("iterator_id", None)
if id is None:
request.session["iterator_id"] = str(uuid.uuid4())
try:
return render(request, "item_template.html", "item": next(sessions_current_iterators)
except StopIteration:
request.session.pop("iterator_id")
return render(request, "end_template.html", )
但是:永远不要在生产环境中使用它!
生成器非常适合在计算请求时减少内存消耗,或者对 tornado web 服务很有用,但显然,django 不应该在局部变量中的请求之间共享数据。
【讨论】:
【参考方案2】:你总是可以在可以使用 return 的地方使用 yield(因为这些是 python 的东西而不是 Django 的东西)。这里唯一需要注意的是,每个请求都会调用相同的函数;因此收益率之后的延续可能会为另一个客户提供服务,而不是您想要的客户。但是,您可以通过使用更高级别的函数(此处的生成器)来解决这个问题。基本上,该函数将有一个生成器字典,该字典由从请求派生的唯一键索引。每次调用该函数时,检查字典中是否已存在该请求的条目。如果没有为该请求添加新功能。然后为给定的请求调用生成器,确保存储生成器产生或返回的任何内容。为了将字典保存在内存中,让 main 函数现在产生存储的值。最后,为了让每次调用main函数都不会清空字典,通过将字典初始化为空字典来启动函数体;然后将其他所有内容包装在无限的while循环中。这将确保 main 函数,也是一个生成器,永远不会真正退出。第一次调用时,字典被初始化;然后开始。同时,如果给定请求不存在任何条目,该函数将创建一个生成器并将其存储在字典中。然后该函数为请求调用生成器并生成生成器返回的任何内容或在 while 底部生成的内容。再次调用时; main 函数在 while 的顶部恢复。代码是这样的:
def main_func(request, *args) :
funcs =
while True:
request_key = make_key(request)
If request_key not in funcs.keys():
def generator_func():
# your generator code here...
# remember to delete the func item in funcs before returning...
funcs[request_key] = generator_func
yield funcs[request_key] ()
def make_key(request):
# quick and dirty impl
return str(request.session)
【讨论】:
以上是关于可以在 Django 视图中使用 Python 生成器吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 django 视图中使用 subprocess.Popen() 执行 python 脚本
在 Python 中使用 Django - 尝试导入时未定义视图