Django is full of shortcuts to make web developers’ lives easier, but all those tools are of no use if you can’t easily deploy your sites. Since Django’s inception, ease of deployment has been a major goal.
There are many options for deploying your Django application, based on your architecture or your particular business needs, but that discussion is outside the scope of what Django can give you as guidance.
Django, being a web framework, needs a web server in order to operate. And since most web servers don’t natively speak Python, we need an interface to make that communication happen.
Django currently supports two interfaces: WSGI and ASGI.
- WSGI is the main Python standard for communicating between web servers and applications, but it only supports synchronous code.
- ASGI is the new, asynchronous-friendly standard that will allow your Django site to use asynchronous Python features, and asynchronous Django features as they are developed.
You should also consider how you will handle static files for your application, and how to handle error reporting.
Finally, before you deploy your application to production, you should run through our deployment checklist to ensure that your configurations are suitable. How to deploy Django.
Upgrade system and install needed packages (dependencies):
sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip python3-dev python3-venv libpq-dev postgresql postgresql-contrib nginx curl git -y
sudo -u postgres psql
postgres=# CREATE DATABASE myproject;
postgres=# CREATE USER myprojectuser WITH PASSWORD 'my_secure_password';
postgres=# ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
postgres=# ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
postgres=# ALTER ROLE myprojectuser SET timezone TO 'UTC';
postgres=# GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/xinit/dev/homepage/manage.py", line 21, in <module>
main()
File "/home/xinit/dev/homepage/manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
utility.execute()
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/core/management/__init__.py", line 413, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/core/management/base.py", line 354, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/core/management/base.py", line 398, in execute
output = self.handle(*args, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/core/management/base.py", line 89, in wrapped
res = handle_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/core/management/commands/migrate.py", line 244, in handle
post_migrate_state = executor.migrate(
^^^^^^^^^^^^^^^^^
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/db/migrations/executor.py", line 91, in migrate
self.recorder.ensure_schema()
File "/home/xinit/dev/homepage/env/lib/python3.11/site-packages/django/db/migrations/recorder.py", line 70, in ensure_schema
raise MigrationSchemaMissing("Unable to create the django_migrations table (%s)" % exc)
django.db.migrations.exceptions.MigrationSchemaMissing: Unable to create the django_migrations table (permission denied for schema public
LINE 1: CREATE TABLE "django_migrations" ("id" serial NOT NULL PRIMA...
^
)
postgres=# ALTER DATABASE myproject OWNER TO myprojectuser;
postgres=# \q
mkdir ~/myproject
cd ~/myproject
python3 -m venv env
source env/bin/activate
pip3 install django
django-admin startproject myproject .
git clone https://gitlab.com/username/myproject.git
cd myproject
python3 -m venv env
source env/bin/activate
pip3 install -r requirements.txt
(env) $ pip3 install gunicorn psycopg2-binaryGunicorn ‘Green Unicorn’ is a Python WSGI HTTP Server for UNIX. It’s a pre-fork worker model ported from Ruby’s Unicorn project. The Gunicorn server is broadly compatible with various web frameworks, simply implemented, light on server resources, and fairly speedy. Gunicorn documentation.
(env) $ nano myproject/myproject/settings.py
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0']
DEBUG = False
DATABASES = {Save and exit settings file.
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'my_secure_password',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
(env) $ python3 manage.py makemigrations
(env) $ python3 manage.py migrate
(env) $ python3 manage.py createsuperuser
(env) $ python3 manage.py collectstatic
(env) $ python3 manage.py runserver 0.0.0.0:8000
http://server_domain_or_IP:8000
(env) $ cd project
(env) $ gunicorn --bind 0.0.0.0:8000 myproject.wsgi
(env) $ deactivate
sudo nano /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
sudo nano /etc/systemd/system/gunicorn.service
[Unit]
Description=Your application's description
Requires=gunicorn.socket
After=network.target
[Service]
User=user
Group=www-data
WorkingDirectory=/home/user/myproject
ExecStart=/home/user/myproject/env/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
myproject.wsgi:application
[Install]
WantedBy=multi-user.target
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
sudo systemctl status gunicorn.socket
file /run/gunicorn.sock
/run/gunicorn.sock: socket
sudo systemctl status gunicorn
curl --unix-socket /run/gunicorn.sock localhost
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
sudo systemctl enable gunicorn
sudo nano /etc/nginx/sites-available/myproject
server {
listen 80;
server_name server_domain_or_IP;
client_max_body_size 20M;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/user/myproject;
}
location /media {
alias /home/user/myproject/media;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location = /robots.txt {
alias /home/user/myproject/robots.txt;
}
}
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl enable nginx
sudo ufw allow 'Nginx Full'