Hi, django fellows!
@andrewgodwin says in DEP-9 that there is no easy way to make django async. I remember he was doing a talk on this and asked the audience: “Why can’t we just add async and await everywere?” The answer, of course, was the fact that we cared about compatibility.
I doubt that. I think the most straightforward way actually works. And it allows for having both blocking and async versions of django with minimal adjustments.
So, let’s suppose we add async’s and await’s everywhere. How will it work? The async case is more or less clear. The django API is not 100% convertable to async, but it’s doable. Even now django has some kind of async API (async for, aget, etc)
Let’s take the blocking usecase (remember that our codebase is all async-await now?). We just make the top-level functions like Model.save
a regular function (an API facade). The functions it calls like Model.save_base
will all be async.
How can we turn an async function into a regular one? (We are using blocking i/o) Very easy:
class Get:
def __await__(self):
return 1
yield
async def f():
return (await Get())
def run(co):
try:
next(co.__await__())
except StopIteration as ex:
return ex.value
else:
assert False, "unreachable"
assert run(f()) == 1
Here we call an async function f
. We make use of the fact that, with blocking i/o, generators never yield anything.
What do you think? Is this the blind spot of the django team or myself?