---
title: "Dukungan asinkronus"
version: 6.0
locale: id
source: https://docs.djangoproject.com/id/6.0/topics/async/
canonical: https://djangodocs.dev/id/6.0/topics/async/
---
# Dukungan asinkronus

Django has support for writing asynchronous ("async") views, along with an
entirely async-enabled request stack if you are running under [ASGI](/id/6.0/howto/deployment/asgi/). Async views will still work under WSGI, but
with a small per-request adaptation cost (see [Penampilan](#async-performance)), and
without the ability to have efficient long-running requests.

Many parts of Django provide asynchronous APIs, including [the ORM](/id/6.0/topics/db/queries/#async-queries), the cache framework, authentication, sessions, and signals.
For other code, the [`sync_to_async()`](#asgiref.sync.sync_to_async) adapter is a low-cost bridge (see
[Penampilan](#async-performance)). A wide range of async-native Python libraries can
also be integrated.

## Tampilan asinkron

Tampilan apapun dapat menyatakan sinkron dengan membuat bagian nya dapat dipanggil mengembalikan coroutine - umumnya, ini dilakukan dengan menggunakan `async def`. Untuk tampilan berdasarkan-fungsi, ini berarti menyatakan keseluruhan tampilan menggunakan `async def`. Untuk tampilan berdasarkan-kelas, ini berarti menyatakan penangan metode HTTP, seperti `get()` dan `post()` sama `async def` (bukan itu `__init__()`, atau `as_view()`).

> **Note**
>
> Django menggunakan `asgiref.sync.iscoroutinefunction` untuk menguji jika tampilan anda asinkron atau tidak. Jika anda menerapkan metode sendiri dari mengembalikan coroutine, pastikan anda menggunakan `asgiref.sync.markcoroutinefunction` sehingga fungsi ini mengembalikan `True`.

Dibawah peladen WSGI , tampilan asinkron akan berjalan sendiri, mutar satu kali acara. Ini berarti anda dapat menggunakan fitur asinkron, seperti permintaan asinkron HTTP bersamaan, tanpa masalah apapun, tetapi anda tidak akan mendapatkan keuntungan dari tumpukan tugas asinkron.

Keuntungan utama adalah kemampuan melayani ratusan hubungan tanpa menggunakan rangkaian Python. Ini mengijinkan anda menggunakan aliran pelan, jajak pendapat panjang, dan jenis tanggapan seru lainnya.

Jika anda ingin menggunakan ini, anda akan butuh mengembangkan Django menggunakan [ASGI](/id/6.0/howto/deployment/asgi/) instead.

> **Note**
>
> A fully asynchronous request stack requires async middleware end-to-end.
> Where a piece of synchronous middleware sits between an ASGI server and an
> async view, Django adapts it by running it in its own thread; see
> [Penampilan](#async-performance) for the cost trade-off.
>
> Django's bundled middleware supports both [sync and async](/id/6.0/topics/http/middleware/#async-middleware). Third-party middleware may not. To see which
> middleware Django adapts, turn on debug logging for the `django.request`
> logger and look for log messages about *"Asynchronous handler adapted for
> middleware ..."*.

Dalam suasana ASGI dan WSGI, anda masih dapat dengan aman menggunakan dukungan asinkron untuk menjalankan kode secara bersamaan daripada berurutan. Ini sangat berguna ketika berhubungan dengan API luar atau penyimpanan data.

Jika anda ingin memanggil bagian dari Django yang masih sinkronis, anda butuh membungkusnya dalam panggilan [`sync_to_async()`](#asgiref.sync.sync_to_async). Sebagai contoh:

```
from asgiref.sync import sync_to_async

results = await sync_to_async(sync_function, thread_sensitive=True)(pk=123)
```

Jika anda secara tidak sengaja mencoba memanggil bagian dari Django yaitu hanya-sinkron dari tampilan asinkron, anda akan membangkitkan [asynchronous safety protection](#async-safety) Django untuk melindungi data anda dari kerusakan.

### Decorator

Decorator berikut dapat digunakan dengan fungsi tampilan sinkron dan asinkron:

- [`cache_control()`](/id/6.0/topics/http/decorators/#django.views.decorators.cache.cache_control)
- [`never_cache()`](/id/6.0/topics/http/decorators/#django.views.decorators.cache.never_cache)
- [`no_append_slash()`](/id/6.0/topics/http/decorators/#django.views.decorators.common.no_append_slash)
- [`csp_override()`](/id/6.0/ref/csp/#django.views.decorators.csp.csp_override)
- [`csp_report_only_override()`](/id/6.0/ref/csp/#django.views.decorators.csp.csp_report_only_override)
- [`csrf_exempt()`](/id/6.0/ref/csrf/#django.views.decorators.csrf.csrf_exempt)
- [`csrf_protect()`](/id/6.0/ref/csrf/#django.views.decorators.csrf.csrf_protect)
- [`ensure_csrf_cookie()`](/id/6.0/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie)
- [`requires_csrf_token()`](/id/6.0/ref/csrf/#django.views.decorators.csrf.requires_csrf_token)
- [`sensitive_variables()`](/id/6.0/howto/error-reporting/#django.views.decorators.debug.sensitive_variables)
- [`sensitive_post_parameters()`](/id/6.0/howto/error-reporting/#django.views.decorators.debug.sensitive_post_parameters)
- [`gzip_page()`](/id/6.0/topics/http/decorators/#django.views.decorators.gzip.gzip_page)
- [`condition()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.condition)
- `conditional_page()`
- [`etag()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.etag)
- [`last_modified()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.last_modified)
- [`require_http_methods()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.require_http_methods)
- [`require_GET()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.require_GET)
- [`require_POST()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.require_POST)
- [`require_safe()`](/id/6.0/topics/http/decorators/#django.views.decorators.http.require_safe)
- [`vary_on_cookie()`](/id/6.0/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie)
- [`vary_on_headers()`](/id/6.0/topics/http/decorators/#django.views.decorators.vary.vary_on_headers)
- `xframe_options_deny()`
- `xframe_options_sameorigin()`
- `xframe_options_exempt()`

Sebagai contoh:

```
from django.views.decorators.cache import never_cache

@never_cache
def my_sync_view(request): ...

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

### Permintaan & ORM

With some exceptions, Django can run ORM queries asynchronously:

```
async for author in Author.objects.filter(name__startswith="A"):
    book = await author.books.afirst()
```

Rincian catatan dapat ditemukan dakam [Asynchronous queries](/id/6.0/topics/db/queries/#async-queries), tapi singkatnya:

- Semua metode `QuerySet` yang dapat menyebabkan sebuah permintaan SQL untuk muncul memiliki asinkron `a`-prefixed  berbeda.
- `async for` didukung pada semua QuerySets (termasuk keluaran `values()` dan `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)
```

Transaksi belum berjalan di suasana asinkron. Jika anda memiliki potongan kode yang butuh perilaku transaksi, kami menganjurkan anda menulis potongan sebagai fungsi sinkron tunggal dan memanggil dia menggunakan [`sync_to_async()`](#asgiref.sync.sync_to_async).

[Persistent database connections](/id/6.0/ref/databases/#persistent-database-connections), set
via the [`CONN_MAX_AGE`](/id/6.0/ref/settings/#std-setting-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.

### Penampilan

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()`](#asgiref.sync.sync_to_async)
(or [`async_to_sync()`](#asgiref.sync.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.

Anda harus melakukan pengujian penampilan sendiri untuk melihat pengaruh apa ASGI melawan WSGI miliki pada kode anda. Di beberapa kasus, ada kemungkinan penampilan meningkat bahkan untuk basis kode yang murni sinkron dibawah ASGI karena semua kode penangan-permintaan masih berjalan asinkron. Secara umum anda hanya ingin mengadakan suasana ASGI jika anda memiliki kode asinkron di proyek anda.

### Handling disconnects

Untuk permintaan berumur-panjang, klien mungkin memutuskan sebelum tampilan mengembalikan tanggapan. Di kasus ini, `asyncio.CancelledError` akan dimunculkan dalam tampilan. Anda dapat menangkap kesalahan ini dan menangani itu jika anda butuh melakukan pembersihan:

```
async def my_view(request):
    try:
        # Do some work
        ...
    except asyncio.CancelledError:
        # Handle disconnect
        raise
```

Anda dapat juga [handle client disconnects in streaming responses](/id/6.0/ref/request-response/#request-response-streaming-disconnect).

## Keamanan asinkronus

#### `DJANGO_ALLOW_ASYNC_UNSAFE`

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.

Jika anda mencoba menjalankan apapun dari bagian ini dari antrian dimana ada *running event loop*, anda akan mendapatkan kesalahan [`SynchronousOnlyOperation`](/id/6.0/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation). Catat bahwa anda tidak harus di dalam fungsi asinkron secara langsung untuk memunculkan kesalahan ini. Jika anda telah memanggil fungsi sinkron secara langsung dari fungsi asinkron, tanpa menggunakan [`sync_to_async()`](#asgiref.sync.sync_to_async) atau semacamnya, kemudian itu dapat juga muncul. Ini karena kode anda masih berjalan dalam urutan dengan putaran kegiatan aktif, meskipun itu mungkin tidak di nyatakan sebagai kode asinkron.

Jika anda mengalami kesalahan ini, anda harus memperbaiki kode anda untuk tidak memanggil kode menyinggung dari konteks asinkron. Sebaiknya, tulis kode anda yang berbicara ke fungsi tidak-aman-asinkron sendiri, fungsi sinkron, dan memanggil itu menggunakan [`asgiref.sync.sync_to_async()`](#asgiref.sync.sync_to_async) (atau cara lain apapun dari menjalankan kode sinkron di antrian sendiri).

Konteks asinkron dapat dibebankan kepada anda dengan lingkungan dimana anda menjalankan kode Django anda. Sebagai contoh, buku catatan [Jupyter](https://jupyter.org/) dan cangkang interaktif [IPython](https://ipython.org) keduanya secara terbuka menyediakan putaran kegiatan aktif sehingga lebih mudah berinteraksi dengan API asinkron.

Jika anda menggunakan cangkang IPython, anda dapat meniadakan putaran kegiatan ini dengan  menjalankan:

```shell
%autoawait off
```

sebagai sebuah perintah pada prompt IPython. Ini akan mengizinkan anda menjalankan kode sinkron tanpa membangkitkan kesalahan [`SynchronousOnlyOperation`](/id/6.0/ref/exceptions/#django.core.exceptions.SynchronousOnlyOperation); bagaimanapun, anda juga tidak dapat untuk `await` API asinkron. Untuk menyalakan putaran kegiatan kembali, jalankan:

```shell
%autoawait on
```

Jika anda berada di lingkungan selain IPython (atau anda tidak dapat mematikan `autoawait` di IPython untuk beberapa alasan), anda *certain* tidak ada kemungkinan kode anda dijalankan secara bersamaan, dan anda *absolutely* butuh menjalankan kode sinkron dari konteks asinkron, kemudian anda dapat meniadakan peringatan dengan menyetel variabel lingkungan [`DJANGO_ALLOW_ASYNC_UNSAFE`](#envvar-DJANGO_ALLOW_ASYNC_UNSAFE) ke nilai apapun.

> **Warning**
>
> Jika Anda mengaktifkan pilihan ini dan ada akses bersamaan ke bagian asinkron-tidak aman dari Django, anda mungkin mengalami kehilangan atau kerusakan data. Berhati-hatilah dan jangan gunakan ini di lingkungan produksi.

Jika anda buth melakukan ini dari dalam Python, lakukan dengan `os.environ`:

```
import os

os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
```

## fungsi  adaptasi asingkronus

Penting untuk menyesuaikan gaya panggilan saat menelepon kode sinron dari konteks asinkron, atau sebaliknya. Untuk ini ada dua fungsi adaptor, dari modul `asgiref.sync`: [`async_to_sync()`](#asgiref.sync.async_to_sync) dan [`sync_to_async()`](#asgiref.sync.sync_to_async). Mereka digunakan untuk transisi antara gaya panggilan sambil menjaga kompatibilitas.

Fungsi adaptor ini banyak digunakan di Django. Paket [asgiref](https://pypi.org/project/asgiref/) itu sendiri adalah bagian dari proyek Django, dan itu dipasang secara otomatis sebagai ketergantungan saat anda memasang Django dengan `pip`.

### `async_to_sync()`

#### `async_to_sync(async_function, force_new_loop=False)`

Mengambil fungsi asinkron dan mengembalikan fungsi sinkronisasi yang membungkusnya. Dapat digunakan sebagai pembungkus langsung atau dekorator

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

Fungsi asinkron dijalankan di putaran kegiatan untuk antrian saat ini, jika ada. Jika tidak ada putaran kegiatan saat ini, putaran kegiatan baru akan diputar secara khusus untuk pemanggilan asinkron tunggal dan dimatikan lagi setelah selesai. Dalam situasi apa pun, fungsi asinkron akan dijalankan pada antrian yang berbeda dengan kode panggilan.

Nilai threadlocal dan contextvar dipertahankan melintasi batas di kedua arah.

[`async_to_sync()`](#asgiref.sync.async_to_sync) is essentially a more powerful version of the
[`asyncio.run()`](https://docs.python.org/3/library/asyncio-runner.html#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()`](#asgiref.sync.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()`](https://docs.python.org/3/library/asyncio-runner.html#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()`

#### `sync_to_async(sync_function, thread_sensitive=True)`

Mengambil fungsi sinkronisasi dan mengembalikan fungsi asinkron yang membungkusnya. Dapat digunakan sebagai pembungkus langsung atau dekorator

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

Nilai threadlocal dan contextvar dipertahankan melintasi batas di kedua arah.

Fungsi sinkronisasi cenderung ditulis dengan asumsi semuanya berjalan di antrian utama, jadi [`sync_to_async()`](#asgiref.sync.sync_to_async) memiliki dua mode antrian:

- `thread_sensitive=True` (awalan): fungsi sinkronisasi akan berjalan di antrian yang sama dengan semua fungsi `thread_sensitive` lainnya. Ini akan menjadi antrian utama, jika antrian utama sinkron dan anda menggunakan pembungkus [`async_to_sync()`](#asgiref.sync.async_to_sync).
- `thread_sensitive=False`: fungsi sinkronisasi akan berjalan di antrian baru yang kemudian ditutup setelah pemanggilan selesai.

Suasana peka utas cukup istimewa, dan melakukan banyak pekerjaan untuk menjalankan semua fungsi di antrian yang sama. Perhatikan, bahwa itu *bergantung pada penggunaan* [`async_to_sync()`](#asgiref.sync.async_to_sync) *di atasnya dalam tumpukan* untuk menjalankan berbagai hal dengan benar di antrian utama. Jika Anda menggunakan `asyncio.run()` atau yang serupa, fungsi ini akan kembali menjalankan fungsi antrian-sensitif dalam satu antrian bersama, tetapi ini tidak akan menjadi antrian utama.

Alasan ini diperlukan di Django adalah bahwa banyak perpustakaan, khususnya adaptor berdasarkan data, mengharuskan mereka diakses di antrian yang sama dengan tempat mereka dibuat. Juga banyak kode Django yang ada menganggap semuanya berjalan di antrian yang sama, mis. middleware menambahkan sesuatu ke permintaan untuk digunakan nanti dalam tampilan.

Daripada memperkenalkan potensi masalah kompatibilitas dengan kode ini, kami memilih untuk menambahkan suasana ini sehingga semua kode sinkronisasi Django yang ada berjalan di antrian yang sama dan dengan demikian sepenuhnya kompatibel dengan suasana asinkron. Perhatikan bahwa kode sinkronisasi akan selalu berada dalam antrian *berbeda* dengan kode asinkron apa pun yang memanggilnya, jadi Anda harus menghindari meneruskan pegangan database mentah atau acuan sensitif antrian lainnya.

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

Dalam praktiknya, pembatasan ini berarti bahwa anda tidak boleh melewatkan fitur objek `connection` basisdata saat memanggil `sync_to_async()`. Melakukannya akan memicu antrian pemeriksaan keamanan:

```pycon
# 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.
```

Sebaliknya, Anda harus mengenkapsulasi semua akses database dalam fungsi pembantu yang dapat dipanggil dengan `sync_to_async()` tanpa bergantung pada objek koneksi dalam suasana panggilan.
