[Django]-Can Python Generators be used in Django Views?

4👍

As Django is synchronous wsgi, you have to process each request as stand alone, your python environment can be killed or switched to an other at any time.

Still if you have no fear and a single process, you can make a file scope dictionary with session ids and iterators that you’ll consume each time

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", {})

but: NEVER USE THIS ON A PRODUCTION ENVIRONMENT!

generators are great to reduce memory consumption while computing the request or can be good for tornado web service, but clearly, django should not share data between request in local variables.

1👍

You can always use yield where you can use return (since these are python stuff not Django stuff). The only caveat here is that the same function is called for every request; so the continuation after the yield may serve another client instead of the one you intend. However you can beat this problem by using a higher level function (generator here). Basically the function will have a dictionary of generators indexed by unique keys derived from the requests. Every time the function is called, check whether an entry already exists for the request in the dictionary. If not add a new function for that request. Then invoke the generator for the given request making sure to store whatever is yielded or returned by the generator. To keep the dictionary in memory let the main function now yield the stored value. Finally, so that the dictionary is not cleared every time the main function is called, start the function body by initializing the dictionary to an empty dictionary; then wrap everything else in an infinite while loop. This will ensure that the main function, also a generator, never really exits. When called the first time, the dictionary is initialized; then the while starts. In the while, the function creates and stores a generator in the dictionary if no entry already exists for the given request. Then the function invokes the generator for the request and yields whatever the generator returns or yields at the bottom of the while. When called again; the main function resumes at the top of the while. The code is like so:

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) 

Leave a comment