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):
Configure PostgreSQL.
Open PostgreSQL console:
Create database:
Create user for project:
Setup client_encoding, default_transaction_isolation and timezone:
Grant privileges for created database to user:
If you get permission denied error like this:
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...
^
)
Here is solution:
Quit from PostgreSQL console:
Setup project.
Create virtual environment, install Django and create new project:
Or clone exist and install requirements:
Install gunicorn and psycopg2-binary:
Gunicorn ‘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.
Project configuration.
Open settings.py file:
Edit allowed hosts:
Set DEBUG value to False:
Set database configuration:
Save and exit settings file.
Migrate the initial database schema to PostgreSQL database:
Create administrative user for project:
Collect static files:
Run server for test:
Open in browser your project:
Check with Gunicorn:
Deactivate virtual environment:
Create systemd socket and service files for Gunicorn.
Create systemd socket file for Gunicorn:
And enter following configuration:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Create systemd service file for Gunicorn:
Enter this configuration:
[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
Start Gunicorn socket:
Check Gunicorn socket file:
Check for the existence of gunicorn.sock file within the /run directory:
Output:
Test socket activation:
Using curl:
Reload daemon and restart Gunicorn:
Configure Nginx with proxy_pass.
Create new server block:
Insert configuration in file:
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;
}
}
Create symlink for new configuration:
Test Nginx configuration for syntax errors:
Restart Nginx:
Open 80 (http) and 443 (https) ports for Nginx: