Add uvicorn and web sockets for Django 3

* Add use_async option to cookiecutter.json
* Add websocket configuration
This commit is contained in:
Andrew-Chen-Wang 2020-03-24 15:40:14 -04:00
parent 0c36c57f2d
commit aee2de347b
9 changed files with 88 additions and 0 deletions

View File

@ -44,6 +44,7 @@
"SparkPost",
"Other SMTP"
],
"use_async": "n",
"use_drf": "n",
"custom_bootstrap_compilation": "n",
"use_compressor": "n",

View File

@ -83,6 +83,9 @@ mail_service:
8. SparkPost_
9. `Other SMTP`_
use_async:
Indicates whether the project should use web sockets with Uvicorn + Gunicorn.
use_drf:
Indicates whether the project should be configured to use `Django Rest Framework`_.

View File

@ -101,6 +101,15 @@ def remove_celery_files():
os.remove(file_name)
def remove_async_files():
file_names = [
os.path.join("config", "asgi.py"),
os.path.join("config", "websocket.py"),
]
for file_name in file_names:
os.remove(file_name)
def remove_dottravisyml_file():
os.remove(".travis.yml")
@ -367,6 +376,9 @@ def main():
if "{{ cookiecutter.use_drf }}".lower() == "n":
remove_drf_starter_files()
if "{{ cookiecutter.use_async }}".lower() == "n":
remove_async_files()
print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)

View File

@ -73,6 +73,8 @@ SUPPORTED_COMBINATIONS = [
{"cloud_provider": "GCP", "mail_service": "SparkPost"},
{"cloud_provider": "GCP", "mail_service": "Other SMTP"},
# Note: cloud_providers GCP and None with mail_service Amazon SES is not supported
{"use_async", "y"},
{"use_async", "n"},
{"use_drf": "y"},
{"use_drf": "n"},
{"js_task_runner": "None"},

View File

@ -6,4 +6,8 @@ set -o nounset
python manage.py migrate
{%- if cookiecutter.use_async %}
/usr/local/bin/uvicorn config.asgi --bind 0.0.0.0:5000 --chdir=/app
{%- else %}
python manage.py runserver_plus 0.0.0.0:8000
{% endif %}

View File

@ -27,4 +27,8 @@ if compress_enabled; then
python /app/manage.py compress
fi
{%- endif %}
{% if cookiecutter.use_async %}
/usr/local/bin/uvicorn config.asgi --bind 0.0.0.0:5000 --chdir=/app
{% else %}
/usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app
{%- endif %}

View File

@ -0,0 +1,41 @@
"""
ASGI config for {{ cookiecutter.project_name }} project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/dev/howto/deployment/asgi/
"""
import os
import sys
from pathlib import Path
from django.core.asgi import get_asgi_application
from .websocket import websocket_application
# This allows easy placement of apps within the interior
# {{ cookiecutter.project_slug }} directory.
app_path = Path(__file__).parents[1].resolve()
sys.path.append(str(app_path / "{{ cookiecutter.project_slug }}"))
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
# if running multiple sites in the same mod_wsgi process. To fix this, use
# mod_wsgi daemon mode with each site in its own daemon process, or use
# os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production"
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
# This application object is used by any ASGI server configured to use this
# file. This includes Django's development server, if the ASGI_APPLICATION
# setting points here.
django_application = get_asgi_application()
# Apply ASGI middleware here.
# from helloworld.asgi import HelloWorldApplication
# application = HelloWorldApplication(application)
async def application(scope, receive, send):
if scope['type'] == 'http':
await django_application(scope, receive, send)
elif scope['type'] == 'websocket':
await websocket_application(scope, receive, send)
else:
raise NotImplementedError(f"Unknown scope type {scope['type']}")

View File

@ -0,0 +1,18 @@
async def websocket_application(scope, receive, send):
while True:
event = await receive()
if event['type'] == 'websocket.connect':
await send({
'type': 'websocket.accept'
})
if event['type'] == 'websocket.disconnect':
break
if event['type'] == 'websocket.receive':
if event['text'] == 'ping':
await send({
'type': 'websocket.send',
'text': 'pong!'
})

View File

@ -16,6 +16,9 @@ django-celery-beat==2.0.0 # https://github.com/celery/django-celery-beat
flower==0.9.3 # https://github.com/mher/flower
{%- endif %}
{%- endif %}
{%- if cookiecutter.use_async %}
uvicorn==0.11.3 # https://github.com/encode/uvicorn
{%- endif %}
# Django
# ------------------------------------------------------------------------------