This document discusses taking Python web applications built with Django from development to production. It covers setting up PostgreSQL for the database, deploying with uWSGI and Nginx, adding asynchronous tasks with Celery and RabbitMQ, testing with UnitTest and coverage, monitoring with Elastic APM and Sentry, and considering options like Elasticsearch, Django Channels, and continuous integration. Honorable mentions are made for Elasticsearch, Django Channels, and continuous integration. Careers at Lofty Labs are also mentioned.
19. We need a real DB
Postgres
CREATE DATABASE myproject;
CREATE USER user WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE user TO
myprojectuser;
pip install psycopg2
DATABASES = {
'default': {
'ENGINE':
'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': user,
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
21. We need a real server
uWSGI + Nginx + Supervisor
22. We need a real server
[uwsgi]
chdir=/path/to/your/project
module=mysite.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000
daemonize=/var/log/uwsgi/yourproject.log
23. We need a real server
# mysite_nginx.conf
upstream django {
server 127.0.0.1:8001;
}
server {
listen 8000;
server_name .example.com;
client_max_body_size 75M;
location /media {
alias /path/to/your/mysite/media;
}
location /static {
alias /path/to/your/mysite/static;
}
location / {
uwsgi_pass django;
include /path/to/your/mysite/uwsgi_params;
}
}
24. We need a real server
Supervisor
supervisorctl start myproject
supervisorctl stop myproject
supervisorctl restart myproject
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
startretries=5
numprocs=1
startsecs=0
process_name=%(program_name)s_%(process_num)02d
stderr_logfile=/var/log/supervisor/%(program_name)s_stderr.log
stderr_logfile_maxbytes=10MB
stdout_logfile=/var/log/supervisor/%(program_name)s_stdout.log
stdout_logfile_maxbytes=10MB
27. What about when I want a front end?
pip install djangorestframework
REST_FRAMEWORK = {
# Use Django's standard
`django.contrib.auth` permissions,
# or allow read-only access for
unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissio
nsOrAnonReadOnly'
]
}
INSTALLED_APPS = (
‘corsheaders’,
‘rest_framework’,
...
)
28. What about when I want a front end?
from django.conf.urls import url, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers,
viewsets
# Serializers define the API representation.
class
UserSerializer(serializers.HyperlinkedModelSeria
lizer):
class Meta:
model = User
fields = ('url', 'username', 'email',
'is_staff')
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
30. What about async?
celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
'mysite.settings')
app = Celery('mysite')
app.config_from_object('django.conf:settings',
namespace='CELERY')
app.autodiscover_tasks()
Celery and Rabbit
settings.py
CELERY_BROKER_URL = 'amqp://localhost'
init.py
from .celery import app as celery_app
__all__ = ['celery_app']
31. What about async?
# Create your tasks here
from celery import app
@app.task()
def add(x, y):
return x + y
@app.task()
def mul(x, y):
return x * y
sum = add.apply_async(args=[1,2])
[program:mysite-celery]
command=/home/mysite/bin/celery worker -A mysite
--loglevel=INFO
directory=/home/mysite/mysite
user=nobody
numprocs=1
stdout_logfile=/home/mysite/logs/celery.log
stderr_logfile=/home/mysite/logs/celery.log
autostart=true
autorestart=true
startsecs=10