mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-02-03 13:14:28 +03:00
Add uvicorn and web sockets for Django 3
* Add use_async option to cookiecutter.json * Add websocket configuration
This commit is contained in:
parent
0c36c57f2d
commit
aee2de347b
|
@ -44,6 +44,7 @@
|
||||||
"SparkPost",
|
"SparkPost",
|
||||||
"Other SMTP"
|
"Other SMTP"
|
||||||
],
|
],
|
||||||
|
"use_async": "n",
|
||||||
"use_drf": "n",
|
"use_drf": "n",
|
||||||
"custom_bootstrap_compilation": "n",
|
"custom_bootstrap_compilation": "n",
|
||||||
"use_compressor": "n",
|
"use_compressor": "n",
|
||||||
|
|
|
@ -83,6 +83,9 @@ mail_service:
|
||||||
8. SparkPost_
|
8. SparkPost_
|
||||||
9. `Other SMTP`_
|
9. `Other SMTP`_
|
||||||
|
|
||||||
|
use_async:
|
||||||
|
Indicates whether the project should use web sockets with Uvicorn + Gunicorn.
|
||||||
|
|
||||||
use_drf:
|
use_drf:
|
||||||
Indicates whether the project should be configured to use `Django Rest Framework`_.
|
Indicates whether the project should be configured to use `Django Rest Framework`_.
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,15 @@ def remove_celery_files():
|
||||||
os.remove(file_name)
|
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():
|
def remove_dottravisyml_file():
|
||||||
os.remove(".travis.yml")
|
os.remove(".travis.yml")
|
||||||
|
|
||||||
|
@ -367,6 +376,9 @@ def main():
|
||||||
if "{{ cookiecutter.use_drf }}".lower() == "n":
|
if "{{ cookiecutter.use_drf }}".lower() == "n":
|
||||||
remove_drf_starter_files()
|
remove_drf_starter_files()
|
||||||
|
|
||||||
|
if "{{ cookiecutter.use_async }}".lower() == "n":
|
||||||
|
remove_async_files()
|
||||||
|
|
||||||
print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)
|
print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,8 @@ SUPPORTED_COMBINATIONS = [
|
||||||
{"cloud_provider": "GCP", "mail_service": "SparkPost"},
|
{"cloud_provider": "GCP", "mail_service": "SparkPost"},
|
||||||
{"cloud_provider": "GCP", "mail_service": "Other SMTP"},
|
{"cloud_provider": "GCP", "mail_service": "Other SMTP"},
|
||||||
# Note: cloud_providers GCP and None with mail_service Amazon SES is not supported
|
# 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": "y"},
|
||||||
{"use_drf": "n"},
|
{"use_drf": "n"},
|
||||||
{"js_task_runner": "None"},
|
{"js_task_runner": "None"},
|
||||||
|
|
|
@ -6,4 +6,8 @@ set -o nounset
|
||||||
|
|
||||||
|
|
||||||
python manage.py migrate
|
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
|
python manage.py runserver_plus 0.0.0.0:8000
|
||||||
|
{% endif %}
|
||||||
|
|
|
@ -27,4 +27,8 @@ if compress_enabled; then
|
||||||
python /app/manage.py compress
|
python /app/manage.py compress
|
||||||
fi
|
fi
|
||||||
{%- endif %}
|
{%- 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
|
/usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app
|
||||||
|
{%- endif %}
|
||||||
|
|
41
{{cookiecutter.project_slug}}/config/asgi.py
Normal file
41
{{cookiecutter.project_slug}}/config/asgi.py
Normal 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']}")
|
18
{{cookiecutter.project_slug}}/config/websocket.py
Normal file
18
{{cookiecutter.project_slug}}/config/websocket.py
Normal 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!'
|
||||||
|
})
|
|
@ -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
|
flower==0.9.3 # https://github.com/mher/flower
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
{%- if cookiecutter.use_async %}
|
||||||
|
uvicorn==0.11.3 # https://github.com/encode/uvicorn
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user