基本上我想在每次调用视图时从数据库返回一个唯一的结果(直到我用完了唯一的对象并且必须重新开始)。我在想,一个简单而优雅的解决方案是使用生成器来处理这个问题。这是否可能,如果是这样,如何通过ORM拉出值来解决这个问题?
我认为会话或利用像Memento这样的设计模式可能是一个解决方案,但我真的很好奇,看看是否以及如何在这种情况下使用Python生成器。
答案 0 :(得分:2)
由于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", {})
但是:永远不要在生产环境中使用它!
生成器非常适合在计算请求时减少内存消耗,或者对龙卷风Web服务有益,但很明显,django不应该在局部变量中的请求之间共享数据。
答案 1 :(得分:1)
你总是可以使用yield来使用return(因为这些是python的东西而不是Django的东西)。这里唯一需要注意的是,每个请求都会调用相同的函数;因此,收益率之后的延续可能会为另一个客户而不是您想要的客户提供服务。但是,您可以通过使用更高级别的功能(此处为生成器)来解决此问题。基本上,该函数将具有由从请求派生的唯一键索引的生成器字典。每次调用该函数时,请检查字典中的请求是否已存在条目。如果没有为该请求添加新功能。然后为给定的请求调用生成器,确保存储生成器生成或返回的任何内容。为了将字典保留在内存中,让main函数现在产生存储的值。最后,为了在每次调用main函数时都不清除字典,通过将字典初始化为空字典来启动函数体;然后在无限循环中包装其他所有内容。这将确保主要功能,也是发电机,永远不会真正退出。第一次调用时,字典被初始化;然后一会儿开始。在while中,如果给定请求不存在任何条目,则该函数在字典中创建并存储生成器。然后该函数为请求调用生成器,并在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)
答案 2 :(得分:0)
你总是可以使用yield来使用return(因为这些是python的东西而不是Django的东西)。这里唯一需要注意的是,每个请求都会调用相同的函数;因此,收益率之后的延续可能会为另一个客户而不是您想要的客户提供服务。但是,您可以通过使用更高级别的功能(此处为生成器)来解决此问题。基本上,该函数将具有由从请求派生的唯一键索引的生成器字典。每次调用该函数时,请检查字典中的请求是否已存在条目。如果没有为该请求添加新功能。然后为给定的请求调用生成器,确保存储生成器生成或返回的任何内容。为了将字典保留在内存中,让main函数现在产生存储的值。最后,为了在每次调用main函数时都不清除字典,通过将字典初始化为空字典来启动函数体;然后在无限循环中包装其他所有内容。这将确保主要功能,也是发电机,永远不会真正退出。第一次调用时,字典被初始化;然后一会儿开始。在while中,如果给定请求不存在任何条目,则该函数在字典中创建并存储生成器。然后该函数为请求调用生成器,并在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...
funcs[request_key] = generator_func
yield funcs[request_key] ()
def make_key(request):
# quick and dirty impl
return str(request.session)
答案 3 :(得分:0)
你总是可以使用yield来使用return(因为这些是python的东西而不是Django的东西)。这里唯一需要注意的是,每个请求都会调用相同的函数;因此,收益率之后的延续可能会为另一个客户而不是您想要的客户提供服务。但是,您可以通过使用更高级别的功能(此处为生成器)来解决此问题。基本上,该函数将具有由从请求派生的唯一键索引的生成器字典。每次调用该函数时,请检查字典中的请求是否已存在条目。如果没有为该请求添加新功能。然后为给定的请求调用生成器,确保存储生成器生成或返回的任何内容。为了将字典保留在内存中,让main函数现在产生存储的值。最后,为了在每次调用main函数时都不清除字典,通过将字典初始化为空字典来启动函数体;然后在无限循环中包装其他所有内容。这将确保主要功能,也是发电机,永远不会真正退出。第一次调用时,字典被初始化;然后一会儿开始。在while中,如果给定请求不存在任何条目,则该函数在字典中创建并存储生成器。然后该函数为请求调用生成器,并在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...
funcs[request_key] = generator_func
yield funcs[request_key] ()
def make_key(request):
# quick and dirty impl
return request.session["id"]