Tacaíocht asincrónachLink to this heading

Tá tacaíocht ag Django chun tuairimí asincrónacha (“async”) a scríobh, mar aon le cruach iarratais atá cumasaithe go hiomlán asinc-chumasaithe má tá tú ag rith fao:doc: ASGI </howto/deployment/asgi/index>. Oibreoidh tuairimí async fós faoi WSGI, ach le pionóis feidhmíochta, agus gan an cumas iarratais éifeachtacha fadtéarmach a bheith acu.

Táimid fós ag obair ar thacaíocht async don ORM agus do chodanna eile de Django. Is féidir leat a bheith ag súil leis seo a fheiceáil in eisiúintí amach anseo. Go dtí seo, is féidir leat an cuibheoir: func: sync_to_async a úsáid chun idirghníomhú le codanna sioncrónaithe de Django. Tá raon iomlán leabharlanna Python asinc-dúchasacha ann freisin ar féidir leat comhtháthú leo.

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__ () ``, ``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:

Code
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:

Mar shampla:

Code
from django.views.decorators.cache import never_cache


@never_cache
def my_sync_view(request): ...


@never_cache
async def my_async_view(request): ...

Fiosrúcháin & an ORMLink to this heading

Le roinnt eisceachtaí, is féidir le Django ceisteanna ORM a reáchtáil go hincrónach freisin:

Code
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 QuerySet a fhágann go dtarlóidh ceist SQL.

  • Tacaítear le async for ar gach cearrSets (lena n-áirítear aschur luachanna () ``agus ``values_list ().)

Tacaíonn Django freisin le roinnt modhanna samhail asincrónach a úsáideann an bunachar sonraí:

Code
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.

feidhmíochtLink to this heading

Agus tú ag rith i mód nach n-oireann leis an radharc (m.sh. radharc async faoi WSGI, nó radharc sioncrónaithe traidisiúnta faoi ASGI), caithfidh Django aithris a dhéanamh ar an stíl glaonna eile chun ligean do chód rith. Is cúis leis an lasc comhthéacs seo pionós feidhmíochta beag de thart ar milleisoicind.

Tá sé seo fíor freisin maidir le middleware. Déanfaidh Django iarracht líon na n-lasc comhthéacs idir sioncrónú agus async a íoslaghdú. Má tá freastalaí ASGI agat, ach tá do mheán-earraí agus do thuairimí go léir sioncrónach, athróidh sé ach uair amháin, sula dtéann sé isteach sa chrac middleware.

Mar sin féin, má chuireann tú meán-earraí sioncrónach idir freastalaí ASGI agus radharc asincrónach, beidh ort aistriú go mód sioncrónaithe don middleware agus ansin ar ais go mód async don radharc. Coinneoidh Django an snáithe sioncrónaithe ar oscailt freisin le haghaidh iomadú eisceachta middleware. B'fhéidir nach mbeidh sé seo faoi deara ar dtús, ach is féidir an pionós seo de snáithe amháin in aghaidh an iarratais a chur leis is féidir aon buntáiste feidhmíochta async a bhaint.

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:

Code
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

Níl príomhchodanna áirithe de Django in ann oibriú go sábháilte i dtimpeallacht async, toisc go bhfuil stát domhanda acu nach bhfuil ar an eolas faoi choirútín. Déantar na codanna seo de Django a aicmiú mar “async-neamhshábháilte”, agus tá siad cosanta ó fhorghníomhú i dtimpeallacht async. Is é an ORM an príomhshampla, ach tá codanna eile ann a chosnaítear ar an mbealach seo freisin.

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:

Shell
%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:

Shell
%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 `:

Code
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:

Code
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.

``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:

Code
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 feidhm thread_sensitive eile. 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.

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:

Python console
# 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.