Asynchronous Pada Django Views

Langkah besar baru saja terjadi pada Framework Django, dimana fitur async views, async middleware dan async test client baru saja ditambahkan kedalam codebase Django pada pull request ini.

Mungkin bagi pengguna Django sebelumnya  sudah terbiasa dengan kode yang berjalan secara synchronous karena framework ini dibuat dimasa python belum support kode asyncronous.

Dengan adanya modul asyncio pada python 3, Django Maintainer  sepakat untuk menambahkan fitur async pada Django agar kita semua bisa memanfaatkan asyncio secara maksimal pada saat melakukan pembuatan aplikasi menggunakan Django.

Saat ini saya mencoba membuat web simple yang menggunakan fitur baru Django langsung dari branch master, dikarenakan saat artikel ini ditulis fitur ini belum secara resmi di rilis ke publik.

Aplikasi yang akan saya buat adalah sebuah web yang akan melakukan web scrapping nilai kurs dinar dan dirham dan melakukan penyimpanan ke database dan memanfaatkan asyncio di semua implementasi views di Django.

Screen Shot 2020-03-21 at 13.00.45

Semua kode bisa di clone disini dan siap dijalankan dan bisa dilihat sekarang kita dapat menggunakan sintak async dan await pada kode views kita.

async def remove_view(request):
    await asyncio.gather(
        sync_to_async(Dinar.objects.all().delete)(),
        sync_to_async(Dirham.objects.all().delete)(),
    )
    return redirect('index')

Beberapa hal yang perlu diperhatikan dalam penggunaan async views adalah:

  • Pendefinisian fungsi views harus menggunakan keyword async.

    async def fetch_view(request):
        ...
    
  • Pemanggilan fungsi coroutine menggunakan sintak await.
    async def fetch_view(request):
        kurs = await get_latest_kurs()
        ...
    

    Pada studi kasus project ini saya membuat web scrapper menggunakan asyncio dan memanggil di dalam views Django.

  • Pemanggilan kode yang bersifat synchronous menggunakan adapter asgiref.
    from asgiref.sync import sync_to_async
    
    dinar_get_all = sync_to_async(Dinar.objects.all)
    dinar_create = sync_to_async(Dinar.objects.create)
    
    await dinar_get_all()
    await sync_to_async(Dirham.objects.filter)(harga_jual__lte=200000)
    

    Perlu diketahui bahwa sampai saat ini Django belum sepenuhnya mendukung fitur asynchronous. Ada beberapa bagian yang masih berjalan secara synchronous, maka kita perlu menggunakan asgiref yang telah menyediakan fungsi converter supaya kode synchronous pada aplikasi kita depat mengembalikan sebuah coroutine dan dipanggil menggunakan sintak await untuk mendapatkan nilainya.

    Seperti contoh diatas, Django ORM masih berjalan secara synchronous dan kita perlu menjalankan menggunakan adapter sync_to_async.

    Contoh lainnya adalah Django template, dimana fungsi render yang biasa kita gunakan harus dijalankan di dalam adapter sync_to_async.

    async def index_view(request):
        list_dinar, list_dirham = await asyncio.gather(
            dinar_get_all(),
            dirham_get_all()
        )
        context = {
            'list_dinar': list_dinar,
            'list_dirham': list_dirham,
        }
        return await sync_to_async(render)(request, 'index.html', context)
    

    Apabila kode yang berjalan secara synchronous dipanggil pada asynchronous views ataupun sebaliknya, Django akan melakukan raise exception SynchronousOnlyOperation.

  • Menggunakan ASGI untuk menjalankan asynchronous Django.
    $ uvicorn dinarkurs.asgi:application --workers 9
    

    Apabila kita ingin aplikasi kita benar-benar berjalan secara async, sangat disarankan kita menjalankan project kita menggunakan ASGI. Secara official Django menyarankan menggunakan uvicorn dan daphne.

Diatas merupakan beberapa poin penting yang perlu diperhatikan saat menggunakan Django secara asyncronous. Sampai saat ini fitur yang saya jabarkan diatas baru bisa dicoba secara stable pada saat rilis selanjutnya di versi 3.1 dan itu juga belum secara keseluruhan karena beberapa bagian seperti Django ORM dan sebagainya masih harus di rewrite untuk bisa support secara full asynchronous tanpa memerlukan adapter dari asgiref .

Update 14 Mei 2020
Django 3.1 alpha 1 sudah resmi di rilis, dan pembaruan requirements.txt pada sample project di github.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.