Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django 4.1のAsynchronous

Django 4.1のAsynchronous

talk about "Asynchronous ORM interface, Asynchronous handlers for class-based views".
Nov 12, 2022
DjangoCongress JP 2022 at NIKKEI Conference Room Nikkei Building
https://djangocongress.jp/

Junya Fukuda

November 12, 2022
Tweet

More Decks by Junya Fukuda

Other Decks in Technology

Transcript

  1. ( 話 ?) •ڈ೥ͷDjangoCongress JP 2021 ͰͷτʔΫΛΞοϓσʔτ͍ͨ͠ •Django 3.2 ASGI

    ରԠ - ͜Θ͘ͳ͍ asyncio جૅͱ async view ͷ࢖͍ॴ IUUQTMPHNJKQUFDIBSUJDMFT •DjangoͷORM͸ͳͥਖ਼ࣜରԠͰ͸ͳ͍ͷ͔ •΋͔ͨ͠͠Βͦ͏ࢥΘΕͨํ΋͍Βͬ͠ΌΔ͔΋͠Ε·ͤΜʢΘͨ͠
  2. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 2012

    2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  3. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 1.8

    LTS 2015 2012 2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  4. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 1.8

    LTS 1.11 LTS 2.0 2017 2015 2012 2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  5. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 1.8

    LTS 1.11 LTS 2.0 2.2 LTS 3.0 2019 2017 2015 2012 2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  6. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 1.8

    LTS 1.11 LTS 2.0 2.2 LTS 3.0 3.2 LTS 4.0 2021 2019 2017 2015 2012 2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  7. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 1.8

    LTS 1.11 LTS 2.0 2.2 LTS 3.0 3.2 LTS 4.0 4.1 2022 2021 2019 2017 2015 2012 2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  8. - Django ⾮同期対応 2005 Django OSS 1.0 1.4 LTS 1.8

    LTS 1.11 LTS 2.0 2.2 LTS 3.0 3.2 LTS 4.0 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2008 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  9. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    3.0 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2.2 LTS •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  10. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    3.0 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio 2.2 LTS •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  11. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    3.0 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await Python 3.5 2.2 LTS •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  12. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    3.0 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await 2016 Python 3.5 asgiref 1.0 2.2 LTS •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  13. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.0 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  14. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.0 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels asgiref 3.0 •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  15. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels asgiref 3.0 3.0 asgiରԠ •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  16. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels asgiref 3.0 3.0 ؔ਺view asgiରԠ •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  17. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels asgiref 3.0 3.0 asgiରԠ ؔ਺view ΫϥεϏϡʔ ORM IF •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  18. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels asgiref 3.0 3.0 asgiରԠ ؔ਺view ΫϥεϏϡʔ ORM IF •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  19. - Django ⾮同期対応 1.4 LTS 1.8 LTS 1.11 LTS 2.0

    2.2 LTS 3.2 LTS 4.1 4.2 LTS 2023 2022 2021 2019 2017 2015 2012 2014 Python 3.4 asyncio async/await asgiref 1.0 2016 Python 3.5 channels asgiref 3.0 3.0 asgiରԠ ؔ਺view ΫϥεϏϡʔ ORM IF DEP 0009: Async-capable DjangoʢDEP͸DjangoͷPEPʣ •Έͳ͞Μ͕ॳΊͯ͞ΘͬͨDjangoͷόʔδϣϯ͸͍ͭ͘Ͱ͠ΐ͏͔ʁ
  20. - asyncio 基本 •ඇಉظॲཧͷίʔυΛॻͨ͘Ίͷඪ४ϥΠϒϥϦ •ຖόʔδϣϯਐԽ ߴϨϕϧAPI͕ॆ࣮ - ͱͯ΋ॻ͖΍͍͢ •ෳ਺ͷλεΫΛಉ࣌ʹॲཧ͢Δ •I/Oό΢ϯυͳॲཧʢDBΞΫηε/HTTPϦΫΤετͳͲʣͰޮՌΛൃش

    •async/await ߏจ •λεΫΛొ࿥͢Δasyncio.create_task() - ʮλεΫʯ = ॲཧͩͱࢥ͍ͬͯͩ͘͞ɻ •ॲཧΛฒߦʹ͢Δasyncio.gather() •ྫ֎΍ΩϟϯηϧΛॊೈʹ asyncio.TaskGroup •αʔυύʔςΟͷϥΠϒϥϦΛ࢖͏৔߹ɺඇಉظରԠ͍ͯ͠Δඞཁ͕͋Δ
  21. Django 63- σΟεύο νϟʔ 63-DPOG Ϗϡʔ ϑΥʔϜ ςϯϓϨʔτ Ϟσϧ DjangoϓϩδΣΫτ

    ϒϥ΢β Webαʔό ΞϓϦέʔγϣϯαʔό ϦΫΤ ετ ֎෦Ϧιʔε ϛυϧ ΢ΣΞ Ϩεϙ ϯε
  22. Django 63- σΟεύο νϟʔ 63-DPOG Ϗϡʔ ϑΥʔϜ ςϯϓϨʔτ Ϟσϧ DjangoϓϩδΣΫτ

    ϒϥ΢β Webαʔό ΞϓϦέʔγϣϯαʔό ϦΫΤ ετ ֎෦Ϧιʔε ϛυϧ ΢ΣΞ Ϩεϙ ϯε ʮݱ৔Ͱ࢖͑ΔDjangoͷڭՊॻʯΛࢀߟʹ͍͖ͤͯͨͩ͞·ͨ͠
  23. Django 63- σΟεύο νϟʔ 63-DPOG Ϗϡʔ ϑΥʔϜ ςϯϓϨʔτ Ϟσϧ DjangoϓϩδΣΫτ

    ϒϥ΢β Webαʔό ΞϓϦέʔγϣϯαʔό ϦΫΤ ετ ֎෦Ϧιʔε ϛυϧ ΢ΣΞ Ϩεϙ ϯε ඇಉظରԠ ΫϥεϕʔεϏϡʔ 03.ΠϯλʔϑΣʔε
  24. Django 63- σΟεύο νϟʔ 63-DPOG Ϗϡʔ ϑΥʔϜ ςϯϓϨʔτ Ϟσϧ DjangoϓϩδΣΫτ

    ϒϥ΢β Webαʔό ΞϓϦέʔγϣϯαʔό ϦΫΤ ετ ֎෦Ϧιʔε ϛυϧ ΢ΣΞ Ϩεϙ ϯε ඇಉظରԠ ΫϥεϕʔεϏϡʔ 03.ΠϯλʔϑΣʔε
  25. Django 63- σΟεύο νϟʔ 63-DPOG Ϗϡʔ ϑΥʔϜ ςϯϓϨʔτ Ϟσϧ DjangoϓϩδΣΫτ

    ϒϥ΢β Webαʔό ΞϓϦέʔγϣϯαʔό ϦΫΤ ετ ֎෦Ϧιʔε ϛυϧ ΢ΣΞ Ϩεϙ ϯε ඇಉظରԠ ΫϥεϕʔεϏϡʔ 03.ΠϯλʔϑΣʔε
  26. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py
  27. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View async def post(self, request, *args, **kwargs): ... async def put(self, request, *args, **kwargs): ... class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py
  28. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View async def post(self, request, *args, **kwargs): ... class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py async def put(self, request, *args, **kwargs): ... ఆٛ࣌ͷ஫ҙ఺
  29. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View async def post(self, request, *args, **kwargs): ... class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py async def put(self, request, *args, **kwargs): ... ఆٛ࣌ͷ஫ҙ఺
  30. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View def post(self, request, *args, **kwargs): ... class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py async def put(self, request, *args, **kwargs): ... ఆٛ࣌ͷ஫ҙ఺
  31. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View def post(self, request, *args, **kwargs): ... class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py async def put(self, request, *args, **kwargs): ... ఆٛ࣌ͷ஫ҙ఺ *NQSPQFSMZ$PO fi HVSFE
  32. ΫϥεϕʔεϏϡʔͷඇಉظରԠ import asyncio from django.http import HttpResponse from django.views import

    View async def post(self, request, *args, **kwargs): ... class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform view logic using await. await asyncio.sleep(1) return HttpResponse("Hello async world!") views.py async def put(self, request, *args, **kwargs): ... ఆٛ࣌ͷ஫ҙ఺
  33. Django/views/generics/base.py class View: ⾮同期対応 @classproperty def view_is_async(cls): handlers = [

    getattr(cls, method) for method in cls.http_method_names if (method != "options" and hasattr(cls, method)) ] if not handlers: return False is_async = asyncio.iscoroutinefunction(handlers[0]) if not all(asyncio.iscoroutinefunction(h) == is_async for h in handlers[1:]): raise ImproperlyConfigured( f"{cls.__qualname__} HTTP handlers must either be all sync or all " "async." ) return is_async
  34. ΫϥεϕʔεϏϡʔಉظίʔυ class PokeView(View): URL = "https://pokeapi.co/api/v2/pokemon/" def get(self, request, *args,

    **kwargs): start = time() pokemons = [] for number in range(1, 152): url = f'https://pokeapi.co/api/v2/pokemon/{number}' r = requests.get(url) pokemon = r.json() pokemons.append({"name" : pokemon['name']}) finish = (time() - start) context = {"pokemons": pokemons, "finish_time": finish} return render(request, “sync.html", context) views.py ֎෦APIΛ࣮ߦ
  35. ΫϥεϕʔεϏϡʔඇಉظίʔυ class AsyncPokeView(View): URL = "https://pokeapi.co/api/v2/pokemon/" async def get(self, request,

    *args, **kwargs): start = time() async with httpx.AsyncClient() as client: tasks = [self.access_url_poke(client, number) for number in range(1, 152)] pokemmons = await asyncio.gather(*tasks, return_exceptions=True) finish = (time() - start) context = {"pokemons": pokemmons, "finish_time": finish} return render(request, "async.html", context) async def access_url_poke(self, client, num: int) -> str: r = await client.get(f"{self.URL}{num}") pokemon = r.json() return {"name": pokemon['name']} views.py ֎෦APIΛ࣮ߦ
  36. 同期 ⾮同期 •࣮ߦ݁Ռ •ಉظɿ18ඵ •ඇಉظɿ0.7ඵ •ඇಉظͱͯ΋͸΍͍ •APIΛ151ճ΋ୟ͘ඇಉظʹ༗རͳܭଌʢͻ͍͖ •ͦͷଞͷ࢖͍ํ - DjangoCon

    2022 •Async Django: The practical guide you've been *awaiting* for by Carlton Gibson •https://www.youtube.com/watch?v=B5uQPwX4VLo •֎෦APIΛಉ࣌ʹ࣮ߦ͢Δ৔߹ʹ࠾༻͠ͳ͍ख͸ͳ͍ •ʮඇಉظDjangoͷ͋ͳ͕ͨ଴ͪ๬ΜͰ͍࣮ͨ༻తͳΨΠυϒοΫʯνϟοτ Channels
  37. ⾮同期 ORM •QuerySetͷϝιουʹ઀಄ࣙʮaʯ͕͍ͭͨඇಉظ൛͕௥Ճ •໋໊نଇ͸3ͭͷީิ 1."_async" pre fi x, 2."_async" suf

    fi x 3."a" pre fi x _async_get get_async aget ଞʹ΋a.getͳͲ •ٞ࿦ͷ຤ɺPythonͷํ޲ੑ(e.g. __aiter__, __anext__, __aenter__, __aexit__ etc.) •3͕࠾༻ʹ IUUQTGPSVNEKBOHPQSPKFDUDPNUOBNJOHPGBTZODWBSJBOUT
  38. ⾮同期 ORM •QuerySetͷϝιουʹ઀಄ࣙʮaʯ͕͍ͭͨඇಉظ൛͕௥Ճ •db.models.guery •aiterator, aaggregate, acount, aget, acreate, abulk_create,

    abulk_update, • aget_or_create, aupdate_or_create, aearliest, alatest, a fi rst, alast, ain_bulk, • aupdate, adelete, aexists, acontains, aexplain •ʢ´-`ʣ.ŇoOʢ໊લ͕ؾʹͳΔ΋ͷ΋͋Δ… acount, aggregate, adelete …ʣ •·ͣ͸؆୯ʹಈ͔ͯ͠Έ·͠ΐ͏
  39. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ
  40. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ In [1]: from django.contrib.auth.models import User
  41. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ In [1]: from django.contrib.auth.models import User In [2]: admin_user = User.objects.get(id=1) In [3]: admin_user Out[3]: <User: admin>
  42. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ In [1]: from django.contrib.auth.models import User In [2]: admin_user = User.objects.get(id=1) In [3]: admin_user Out[3]: <User: admin> In [4]: admin_user = User.objects.aget(id=1)
  43. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ In [1]: from django.contrib.auth.models import User In [2]: admin_user = User.objects.get(id=1) In [3]: admin_user Out[3]: <User: admin> In [4]: admin_user = User.objects.aget(id=1) In [5]: admin_user Out[5]: <coroutine object QuerySet.aget at 0x107b36110>
  44. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ In [1]: from django.contrib.auth.models import User In [2]: admin_user = User.objects.get(id=1) In [3]: admin_user Out[3]: <User: admin> In [4]: admin_user = User.objects.aget(id=1) In [6]: admin_user = await User.objects.aget(id=1) In [5]: admin_user Out[5]: <coroutine object QuerySet.aget at 0x107b36110>
  45. ΫϥεϕʔεϏϡʔඇಉظίʔυ $ python manage.py shell Python 3.11.0 (v3.11.0:deaf509e8f, Oct 24

    2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)] Type 'copyright', 'credits' or 'license' for more information IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help. views.py ֎෦APIΛ࣮ߦ In [1]: from django.contrib.auth.models import User In [2]: admin_user = User.objects.get(id=1) In [3]: admin_user Out[3]: <User: admin> In [4]: admin_user = User.objects.aget(id=1) In [6]: admin_user = await User.objects.aget(id=1) In [7]: admin_user Out[7]: <User: admin> In [5]: admin_user Out[5]: <coroutine object QuerySet.aget at 0x107b36110>
  46. ΫϥεϕʔεϏϡʔಉظίʔυ class SyncOrmView(View): def get(self, request, *args, **kwargs): start =

    time() users = [] for _ in range(100_000): users.append(User(name="Taro")) snippets = [] for _ in range(100_000): snippets.append(Snippet(title="PingPong")) User.objects.bulk_create(users) Snippet.objects.bulk_create(snippets) finish = (time() - start) context = {"finish_time": finish} return render(request, "sync.html", context) views.py ORM
  47. ΫϥεϕʔεϏϡʔಉظίʔυ class AsyncOrmView(View): async def post(self, request, *args, **kwargs): start

    = time() users = [] for _ in range(100_000): users.append(User(name="Taro")) snippets = [] for _ in range(100_000): snippets.append(Snippet(title="PingPong")) await asyncio.gather( self.check("user", User, users), self.check("snippet", Snippet, snippets) ) finish = (time() - start) context = {"finish_time": finish} return render(request, "async.html", context) async def check(self, name, model, data): print(f"start {name}") await model.objects.abulk_create(data) print(f"end {name}") views.py ORM
  48. abulk_create async def abulk_create( self, objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None,

    unique_fields=None, ): return await sync_to_async(self.bulk_create)( objs=objs, batch_size=batch_size, ignore_conflicts=ignore_conflicts, update_conflicts=update_conflicts, update_fields=update_fields, unique_fields=unique_fields, )
  49. abulk_create async def abulk_create( self, objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None,

    unique_fields=None, ): return await sync_to_async(self.bulk_create)( objs=objs, batch_size=batch_size, ignore_conflicts=ignore_conflicts, update_conflicts=update_conflicts, update_fields=update_fields, unique_fields=unique_fields, )
  50. sync_to_async •ίʔϧόοΫʹࢦఆ͞Εͨಉظؔ਺ʢ͜ͷ৔߹getʣΛඇಉظͬΆ࣮͘ߦͯ͠ฦ͢ def sync_to_async( func=None, thread_sensitive=True, executor=None, ): if func

    is None: return lambda f: SyncToAsync( f, thread_sensitive=thread_sensitive, executor=executor, ) return SyncToAsync( func, thread_sensitive=thread_sensitive, executor=executor, ) BTHJSFGTZODQZ
  51. SyncToAsync •ThreadPoolExecutorΛར༻͠ɺಉظؔ਺ΛΠϕϯτϧʔϓ಺Ͱ࣮ߦ͢Δ class SyncToAsync: ... async def __call__(self, *args, **kwargs):

    loop = asyncio.get_running_loop() ... executor = AsyncToSync.loop_thread_executors[loop] future = loop.run_in_executor( executor, functools.partial( self.thread_handler, loop, self.get_current_task(), sys.exc_info(), func, *args, **kwargs, ),
  52. SyncToAsync •ThreadPoolExecutorΛར༻͠ɺಉظؔ਺ΛΠϕϯτϧʔϓ಺Ͱ࣮ߦ͢Δ class SyncToAsync: ... async def __call__(self, *args, **kwargs):

    loop = asyncio.get_running_loop() ... executor = AsyncToSync.loop_thread_executors[loop] future = loop.run_in_executor( executor, functools.partial( self.thread_handler, loop, self.get_current_task(), sys.exc_info(), func, *args, **kwargs, ), Πϕϯτϧʔϓ಺Ͱ&YFDVUPSΛ࢖͏
  53. DEP 0009: Async-capable Django •ʢDEP͸DjangoͷPEPʣ •Sequencing ͱͯ͠3ஈ֊ •First round (hopefully

    in 3.0) •Further individual projects •Second round (hopefully in 3.1) IUUQTHJUIVCDPNEKBOHPEFQTCMPCNBJOBDDFQUFEBTZODSTU
  54. DEP 0009: Async-capable Django •ʢDEP͸DjangoͷPEPʣ •Sequencing ͱͯ͠3ஈ֊ •First round (hopefully

    in 3.0) •Further individual projects •Second round (hopefully in 3.1) •ORM (async-wrapper interface around existing sync core) •طଘͷಉظίΞʹରԠͨ͠ඇಉظϥούʔΠϯλϑΣʔε •ORM (native async with sync wrappers for backwards compatibility) ޙํޓ׵ੑͷͨΊͷಉظϥούʔΛඋ͑ͨωΠςΟϒඇಉظ IUUQTHJUIVCDPNEKBOHPEFQTCMPCNBJOBDDFQUFEBTZODSTU
  55. DEP 0009: Async-capable Django •ʢDEP͸DjangoͷPEPʣ •Sequencing ͱͯ͠3ஈ֊ •First round (hopefully

    in 3.0) •Further individual projects •Second round (hopefully in 3.1) •ORM (async-wrapper interface around existing sync core) •طଘͷಉظίΞʹରԠͨ͠ඇಉظϥούʔΠϯλϑΣʔε •ORM (native async with sync wrappers for backwards compatibility) ޙํޓ׵ੑͷͨΊͷಉظϥούʔΛඋ͑ͨωΠςΟϒඇಉظ IUUQTHJUIVCDPNEKBOHPEFQTCMPCNBJOBDDFQUFEBTZODSTU ࣮૷ॱং͸༧ఆͲ͓Γʂ
  56. 4.1 ORM 🤔 •Θͨ͠ͷߟ͑Δཧ༝͸3ͭ •ޓ׵ੑ •ޓ׵ੑΛҡ࣋͢Δํ๏Ͱ࣮૷ΛਐΊ͍ͯΔ •ʢ૝૾ʣࢿۚ΋Өڹ͕͋Δͷ͔ʁ •IF͔ΒରԠ͢Δͷ͸౰ॳͷ༧ఆͲ͓Γ •ඇಉظରԠͷϝΠϯ։ൃऀͷϦιʔεෆ଍ 🤔

    •DEP 9 / asgiref ͷ Andrew Godwin ࢯ •PyConJP 2022ͷΩʔϊʔτͷ࿩ʢFaster C Pythonʣ💰 •DEP͸ͦΕ΄Ͳ֬ݻͨΔ࢓༷Ͱ͸ͳͦ͞͏ʢ໋໊نଇ΋มߋʹͳͬͯΔ •DEP 9 Ͱ͸ࢿۚௐୡͷ࿩΋ग़͍ͯΔ Donationͷϖʔδ΋
  57. 謝辞 •Asynchronous ORM •https://forum.djangoproject.com/t/asynchronous-orm/5925/21 •ݱ৔Ͱ࢖͑Δ Django ͷڭՊॻ - ԣ੉ ໌ਔ(ஶ)

    •https://akiyoko.booth.pm/items/1059917 •࣮ફDjango PythonʹΑΔຊ֨WebΞϓϦέʔγϣϯ։ൃ - ࣳా ক (ஶ) •https://www.shoeisha.co.jp/book/detail/9784798153964 • Async Django: The practical guide you've been *awaiting* for by Carlton Gibson - DjangoCon Europe 2022 •https://www.youtube.com/watch?v=Lfe2zsGS0Js • Keynote: State of the Object-Relational Mapping (ORM) - Simon Charette •https://2022.djangocon.us/talks/keynote-state-of-orm/