Tacaíocht asincrónachLink to this heading
Django has support for writing asynchronous ("async") views, along with an entirely async-enabled request stack if you are running under ASGI. Async views will still work under WSGI, but with a small per-request adaptation cost (see feidhmíocht), and without the ability to have efficient long-running requests.
Many parts of Django provide asynchronous APIs, including the ORM, the cache framework, authentication, sessions, and signals.
For other code, the sync_to_async() adapter is a low-cost bridge (see
feidhmíocht). A wide range of async-native Python libraries can
also be integrated.
Tuairimí asyncLink to this heading
Is féidir aon radharc a dhearbhú async tríd an gcuid inghlaonta de coroutine a thabhairt ar ais - go coitianta, déantar é seo ag baint úsáide as async def. Maidir le dearcadh bunaithe ar fheidhm, ciallaíonn sé seo an dearcadh iomlán a dhearbhú ag baint úsáide as async def. Maidir le dearcadh rang-bhunaithe, ciallaíonn sé seo láimhseálaithe modh HTTP a dhearbhú, mar shampla get () ``agus ``post () mar async def` (ní a __init__ () ``, nó ``as_view ()).
Faoi fhreastalaí WSGI, reáchtálfaidh tuairimí async ina lúb imeachta aonuaire féin. Ciallaíonn sé seo gur féidir leat gnéithe async a úsáid, cosúil le hiarratais HTTP async comhthráthacha, gan aon cheisteanna, ach ní gheobhaidh tú na buntáistí a bhaineann le cruach async.
Is iad na príomhbhuntáistí an cumas na céadta naisc a sheirbheáil gan snáitheanna Python a úsáid. Ligeann sé seo duit sruthú mall, vótaíocht fhada, agus cineálacha freagartha spreagúla eile a úsáid.
Más mian leat iad seo a úsáid, beidh ort Django a úsáid ag baint úsáidea:doc: ASGI ina ionad </howto/deployment/asgi/index>.
I mód ASGI agus WSGI araon, is féidir leat tacaíocht asincrónach a úsáid go sábháilte fós chun cód a reáchtáil ag an am céanna seachas go sraitheach. Tá sé seo áisiúil go háirithe agus tú ag déileáil le APIs seachtracha nó stórais sonraí.
Más mian leat glaoch ar chuid de Django atá fós sioncrónach, beidh ort é a fhilleadh i nglao a:func: sync_to_async. Mar shampla:
from asgiref.sync import sync_to_async
results = await sync_to_async(sync_function, thread_sensitive=True)(pk=123)
<async-safety>Má dhéanann tú iarracht de thaisme glaoch ar chuid de Django atá sioncrónach amháin ó radharc async, spreagfaidh tú Django's:ref: `cosaint sábháilteachta asincrónach `chun do chuid sonraí a chosaint ar éilliú.
MaisitheoiríLink to this heading
Is féidir na maisitheoirí seo a leanas a úsáid le feidhmeanna amharc sioncrónach agus asincrónach araon:
``leathanach_coinníollacha () ``
``xframe_options_deny () ``
``xframe_options_sameorigin () ``
``xframe_options_díolmhaithe () ``
Mar shampla:
from django.views.decorators.cache import never_cache
@never_cache
def my_sync_view(request): ...
@never_cache
async def my_async_view(request): ...
method_decorator() can be used with asynchronous
methods, including async def view handlers. Note, though, that if
decorating dispatch() on a View with
asynchronous handlers, you will need to override dispatch to make it
async def as well:
class MyClass(View):
@method_decorator(never_cache)
async def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
async def get(self, request): ...
async def post(self, request): ...
Here, because we are decorating dispatch, rather than the individual
handler methods, we need to make dispatch asynchronous so that
method_decorator can correctly mark the resulting method as a coroutine
function.
Fiosrúcháin & an ORMLink to this heading
With some exceptions, Django can run ORM queries asynchronously:
async for author in Author.objects.filter(name__startswith="A"):
book = await author.books.afirst()
Is féidir nótaí mionsonraithe a fháil in:ref: async-queries, ach i mbeagán focal:
Tá leagan asincrónach réamhshocraithe ag gach modh
QuerySeta fhágann go dtarlóidh ceist SQL.Tacaítear le
async forar gach cearrSets (lena n-áirítear aschurluachanna () ``agus ``values_list ().)
Asynchronous model methods that use the database are also supported:
async def make_book(*args, **kwargs):
book = Book(...)
await book.asave(using="secondary")
async def make_book_with_tags(tags, *args, **kwargs):
book = await Book.objects.acreate(...)
await book.tags.aset(tags)
Ní oibríonn idirbhearta fós i mód async. Má tá píosa cód agat a dteastaíonn iompar idirbhearta uaidh, molaimid duit an píosa sin a scríobh mar fheidhm sioncrónach amháin agus glaoch air ag baint úsáid:func: sync_to_async.
Persistent database connections, set
via the CONN_MAX_AGE setting, should also be disabled in async mode.
Instead, use your database backend's built-in connection pooling if available,
or investigate a third-party connection pooling option if required. As in
synchronous Django, concurrent requests in a single process share that pool, so
size it to the target in-flight query concurrency.
feidhmíochtLink to this heading
When running in a mode that does not match the view (e.g. an async view under WSGI, or a traditional sync view under ASGI), Django must emulate the other call style to allow your code to run. The per-call cost of this adaptation is small: tens of microseconds in the in-request ASGI path, where the running event loop is reused, and a few hundred microseconds in the cold-start path used by management commands, background tasks, and scripts. Against typical request times measured in milliseconds, this is rarely visible in itself, but can become so under GIL contention as the number of active threads grows.
If you find yourself wrapping individual rows or operations in a tight loop,
restructure your code so the loop runs inside a single sync_to_async()
(or async_to_sync()) crossing. The per-call cost of the context switch is
then spread across the whole loop and effectively disappears.
The same per-call adaptation cost applies to middleware. Django will attempt to minimize the number of context-switches between sync and async. If you have an ASGI server, but all your middleware and views are synchronous, it will switch just once, before it enters the middleware stack.
However, if you put synchronous middleware between an ASGI server and an asynchronous view, it will have to switch into sync mode for the middleware and then back to async mode for the view. Django will also hold the sync thread open for middleware exception propagation. For request/response views that hit the ORM and return, this is not usually a meaningful penalty. It matters most when you are using ASGI for high in-process concurrency over non-ORM I/O (for example upstream HTTP fan-out, server-sent events, or other long-lived requests), where the extra thread per request caps that concurrency.
Ba chóir duit do thástáil feidhmíochta féin a dhéanamh chun a fháil amach cén éifeacht atá ag ASGI i gcoinne WSGI ar do chód. I roinnt cásanna, d'fhéadfadh go mbeadh méadú feidhmíochta ann fiú le haghaidh bunachar cóid sioncrónach amháin faoi ASGI toisc go bhfuil an cód láimhseála iarratais fós ag rith go gascrónach. Go ginearálta ní bheidh tú ag iarraidh modh ASGI a chumasú ach má tá cód asincrónach agat i do thionscadal.
Dícheangail láimhseáilLink to this heading
Maidir le hiarratais fadré, féadfaidh cliant a dhícheangal sula dtugann an radharc freagra ar ais. Sa chás seo, ardófar Asyncio.CancelleDerror sa radharc. Is féidir leat an earráid seo a ghabháil agus é a láimhseáil más gá duit aon ghlanadh a dhéanamh:
async def my_view(request):
try:
# Do some work
...
except asyncio.CancelledError:
# Handle disconnect
raise
<request-response-streaming-disconnect>Is féidir leat freis:ref: `dícheangail cliant a láimhseáil i bhfreagraí sruthú `.
Sábháilteacht asyncLink to this heading
- DJANGO_ALLOW_ASYNC_UNSAFELink to this definition
Certain key parts of Django are not able to operate safely in an async environment, as they have global state that is not coroutine-aware. These parts of Django are classified as "async-unsafe", and are protected from execution in an async environment. The synchronous API of the ORM is the main example, but there are other parts that are also protected in this way.
Má dhéanann tú iarracht aon cheann de na codanna seo a reáchtáil ó snáithe ina bhfuil lúb imeachta reath* ann, gheobhaidh tú:: exc: ~Django.Core.Exceptions.SynchronousOnlyOperation earráid. Tabhair faoi deara nach gá duit a bheith taobh istigh de fheidhm async go díreach chun an earráid seo a tharlóidh. Má ghlaoigh tú feidhm sioncrónaithe go díreach ó fheidhm async, gan úsáid: func: sync_to_async nó den chineál céanna, ansin is féidir leis tarlú freisin. Tá sé seo toisc go bhfuil do chód fós ag rith i snáithe le lúb imeachta gníomhach, cé nach bhféadfar é a dhearbhú mar chód async.
Má thagann tú ar an earráid seo, ba cheart duit do chód a shocrú chun gan an cód ciontach a ghlaoch ó chomhthéacs async. Ina áit sin, scríobh do chód a labhraíonn le feidhmeanna async-neamhshábháilte ina fheidhm sioncrónaithe féin, agus glaoigh air sin ag baint úsáid:func: asgiref.sync.sync_to_async (nó aon bhealach eile chun cód sioncrónaithe a reáchtáil ina snáithe féin).
Is féidir leis an timpeallacht ina bhfuil do chód Django á reáchtáil agat an comhthéacs async a fhorchur ort. Mar shampla, soláthraíonn leabhair nótaí Jupyter agus sliogáin idirghníomhacha iPython lúb imeachta gníomhach go trédhearcach ionas go mbeidh sé níos éasca idirghníomhú le APIs asincrónacha.
Má tá blaosc IPython á úsáid agat, is féidir leat an lúb imeachta seo a dhíchumasú trí rith:
%autoawait off
mar ordú ag an iPython pras. Ligfidh sé seo duit cód sioncrónach a reáchtáil gan earráidí: exc: ~django.core.exceptions.synchronousOnlyOperation a ghiniúint; áfach, ní bheidh tú in ann APIs asincrónacha feith a dhéanamh freisin. Chun lúb an imeachta a chasadh ar ais, rith:
%autoawait on
Má tá tú i dtimpeallacht seachas IPython (nó mura féidir leat ``autowait ``a mhúchadh i iPython ar chúis éigin), tá tú cinnte* nach bhfuil aon seans ann go ndéanfar do chód a reáchtáil ag an am céanna, agus ní mór duit go hiomlán do chód sioncrónaithe a reáchtáil ó chomhthéacs async, ansin is féidir leat an rabhadh a dhíchumasú trí:envvar: DJANGO_ALLOW_ASYNC_UNEAFE_ASYNC_UN comhshaoil athraitheach go luach ar bith.
Más gá duit é seo a dhéanamh ó laistigh de Python, déan é sin le os.environment `:
import os
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
Feidhmeanna cuibheoir asyncLink to this heading
Is gá an stíl ghlaonna a oiriúnú agus tú ag glaoch ar chód sioncrónaithe ó chomhthéacs async, nó a mhalairt. Chuige seo tá dhá fheidhm oiriúnaitheora ann, ón modúl asgiref.sync: :func: async_to_sync agus:func: sync_to_async. Úsáidtear iad chun aistriú idir na stíleanna glaonna agus comhoiriúnacht á chaomhnú.
Úsáidtear na feidhmeanna cuibheora seo go forleathan i Django. Tá an pacáiste: pypi: asgiref féin mar chuid de thionscadal Django, agus suiteáiltear é go huathoibríoch mar spleáchas nuair a shuiteálann tú Django le pip.
``async_to_sync () ``Link to this heading
- async_to_sync(async_function, force_new_loop=False)Link to this definition
Glacann sé feidhm async agus filleann sé feidhm sioncrónaithe a fhilleann é. Is féidir é a úsáid mar fhilleadh díreach nó mar mhaisitheoir:
from asgiref.sync import async_to_sync
async def get_data(): ...
sync_get_data = async_to_sync(get_data)
@async_to_sync
async def get_other_data(): ...
Reáchtáiltear an fheidhm async sa lúb imeachta don snáithe reatha, má tá ceann i láthair. Mura bhfuil lúb imeachta reatha ann, déantar lúb imeachta nua a chasadh suas go sonrach don iontráil async aonair agus dúnadh síos arís nuair a bheidh sé críochnaithe. I gceachtar cás, déanfaidh an fheidhm async a fhorghníomhú ar snáithe difriúil leis an gcód glaonna.
Caomhnaítear luachanna snáithe agus comhthéacsúla thar an teorainn sa dá threo.
async_to_sync() is essentially a more powerful version of the
asyncio.run() function in Python's standard library. As well as ensuring
threadlocals work, it also enables the thread_sensitive mode of
sync_to_async() when that wrapper is used below it. In the cold path
(no running event loop) it pays the cost of starting a fresh event loop, like
asyncio.run(); when an event loop is already running (the in-request ASGI
case), the running loop is reused and the cost drops accordingly.
``sync_to_async () ``Link to this heading
- sync_to_async(sync_function, thread_sensitive=True)Link to this definition
Glacann sé feidhm sioncrónaithe agus filleann sé feidhm async a fhilleann é. Is féidir é a úsáid mar fhilleadh díreach nó mar mhaisitheoir:
from asgiref.sync import sync_to_async
async_function = sync_to_async(sync_function, thread_sensitive=False)
async_function = sync_to_async(sensitive_sync_function, thread_sensitive=True)
@sync_to_async
def sync_function(): ...
Caomhnaítear luachanna snáithe agus comhthéacsúla thar an teorainn sa dá threo.
Is gnách go scríobhtar feidhmeanna sioncrónaithe ag glacadh leis go ritheann siad go léir sa phríomhsnáithe, mar sin: func: tá dhá mhodh snáithe ag sync_to_async:
thread_sensitive=True(an réamhshocraithe): rithfidh an fheidhm sioncrónaithe sa snáithe céanna le gach feidhmthread_sensitiveeile. Is é seo an príomh-snáithe, má tá an príomh-snáithe sioncrónach agus má tá an fillteán: func: async_to_sync á úsáid agat.thread_sensitive=False: reáchtálfaidh an fheidhm sioncrónaithe i snáithe úrnua a dhúnadh ansin nuair a bheidh an t-ionghairm críochnaithe.
Tá modh íogair do snáithe speisialta go leor, agus déanann sé go leor oibre chun gach feidhm a reáchtáil sa snáithe céanna. Tabhair faoi deara, áfach, go mbraitheann sé ar úsáid*: func: async_to_sync os cionn é sa chrú chun rudaí a reáchtáil i gceart ar an bpríomh-snáithe. Má úsáideann tú ``asyncio.run () ``nó dá leithéid, tiocfaidh sé ar ais ar fheidhmeanna íogair snáithe a reáchtáil i snáithe amháin, roinnte, ach ní hé seo an príomh-snáithe.
Is é an fáth a bhfuil gá leis seo i Django ná go n-éilíonn go leor leabharlanna, go sonrach oiriúnaitheoirí bunachar sonraí, go ndéantar rochtain orthu sa snáithe céanna a cruthaíodh iad. Chomh maith leis sin glacann go leor de chód Django atá ann cheana go ritheann sé go léir sa snáithe céanna, m.sh. middleware ag cur rudaí le hiarratas lena n-úsáid níos déanaí i dtuairimí.
Seachas saincheisteanna comhoiriúnachta féideartha a thabhairt isteach leis an gcód seo, roghnaíomar ina ionad sin an modh seo a chur leis ionas go rithfidh gach cód sioncrónaithe Django atá ann cheana sa snáithe céanna agus dá bhrí sin go mbeidh sé comhoiriúnach Tabhair faoi deara go mbeidh cód sioncrónaithe i snáith* difriol* i gcónaí le haon chód async atá ag glaoch air, mar sin ba cheart duit láimhseálacha bunachar sonraí amh nó tagairtí eile atá íogair do shnáithe a sheachaint timpeall.
Within a single request, multiple thread_sensitive calls serialize on that
request's worker thread, but each request gets its own per-context worker, so
concurrent requests do not serialize against each other. This mirrors
Django's connection-per-thread model, and the same constraint applies in other
async database libraries, where concurrent queries on a single connection
serialize on a lock. To support more concurrent requests, increase the
connection pool size accordingly rather than disabling thread_sensitive.
Go praiticiúil ciallaíonn an srian seo nár chóir duit gnéithe den réad bunachar sonraí nasc` a rith agus tú ag glaoch ar sync_to_async () `. Spreagfaidh sé sin na seiceálacha sábháilteachta snáithe:
# DJANGO_SETTINGS_MODULE=settings.py python -m asyncio
>>> import asyncio
>>> from asgiref.sync import sync_to_async
>>> from django.db import connection
>>> # In an async context so you cannot use the database directly:
>>> connection.cursor()
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from
an async context - use a thread or sync_to_async.
>>> # Nor can you pass resolved connection attributes across threads:
>>> await sync_to_async(connection.cursor)()
django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread
can only be used in that same thread. The object with alias 'default' was
created in thread id 4371465600 and this is thread id 6131478528.
Ina ionad sin, ba cheart duit gach rochtain bunachar sonraí a chumhdú laistigh de fheidhm chúntóra ar féidir a ghlaoch le `sync_to_async () `gan brath ar an réad nasc sa chód glaonna.