Django is a high-level Python web framework. It is developed by experienced developers who help you develop complex and database-driven Python applications without hassle. It follows the model–template–views architectural pattern and has a set of Python scripts for creating Python projects. Django can be installed on many operating systems including, Windows, macOS, Linux/Unix, and Solaris. With Django, you can create a new website in a short amount of time.

This tutorial will explain how to set up Django in Python virtual environment using the PostgreSQL database on Ubuntu 22.04.

Prerequisites

  • A server running Ubuntu 22.04.
  • A valid domain name is pointed to your server IP.
  • A root password is configured on the server.

Update the System

Before starting, I would recommend updating your system packages to the latest version. You can do it using the following command:

apt update -y
apt upgrade -y

After updating all the system packages, install other Python tools and the Nginx package with the following command:

apt-get install python3-pip python3-dev libpq-dev curl nginx -y

Once all the required packages are installed, you can proceed to the next step.

Install and Configure PostgreSQL

In this post, we will use PostgreSQL as a database backend. So, the PostgreSQL server must be installed on your server. If not installed you can install it with the following command.

apt install postgresql postgresql-contrib -y

After installing the PostgreSQL server, run the following command to connect to the PostgreSQL shell:

sudo -i -u postgres
psql

Next, create a database and user for Django with the following command:

CREATE DATABASE djangodb;
CREATE USER djangouser WITH PASSWORD 'password';

Next, grant some required roles with the following command:

ALTER ROLE djangouser SET client_encoding TO 'utf8';
ALTER ROLE djangouser SET default_transaction_isolation TO 'read committed';
ALTER ROLE djangouser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE djangodb TO djangouser;

Next, exit from the PostgreSQL shell using the following command:

q
exit

At this point, the PostgreSQL database is ready for Django. You can now proceed to the next step.

Create a Python Virtual Environment

First, upgrade the PIP package to the latest version using the following command:

pip3 install --upgrade pip

Next, verify the PIP version using the following command:

pip --version

Sample output:

pip 22.3.1 from /usr/local/lib/python3.10/dist-packages/pip (python 3.10)

Next, install the Virtual environment package using the following command:

pip3 install virtualenv

Next, create a directory for the Django project and create a Django virtual environment:

mkdir /var/www/html/djangoapp
cd /var/www/html/djangoapp
virtualenv djangoenv

Next, activate the Django virtual environment using the command below:

source djangoenv/bin/activate

Next, install the Django, Gunicorn, and other packages using the following command:

pip install django gunicorn psycopg2-binary

At this point, Django is installed in the Python virtual environment. Now, you can proceed to the next step.

Install and Configure Django

Django provides a django-admin script to create a project. You can run the following command to create a Django project:

django-admin startproject djangoapp .

Next, you will need to edit the settings.py and define your database settings:

nano /var/www/html/djangoapp/djangoapp/settings.py

Change the following line with your domain name:

ALLOWED_HOSTS = ['django.example.com', 'localhost']

Comment the default database backend and add the PostgreSQL database settings:

#DATABASES = {
#    'default': {
#        'ENGINE': 'django.db.backends.sqlite3',
#        'NAME': BASE_DIR / 'db.sqlite3',
#    }
#}

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'djangodb',
        'USER': 'djangouser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',

    }
}

Add the following lines at the end of the file:

STATIC_URL = '/static/'
import os
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

Save and close the file then migrate the initial database schema to the PostgreSQL database:

./manage.py makemigrations
./manage.py migrate

Sample output:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Next, create a super user account for Django with the following command:

./manage.py createsuperuser

Set your admin username and password as shown below:

Username (leave blank to use 'root'): djangoadmin
Email address: [email protected]
Password: 
Password (again): 
Superuser created successfully.

Next, gather all the static content into the directory:

./manage.py collectstatic

Run the Django Development Server

At this point, Django is installed and configured. You can now start the Django development server using the following command:

./manage.py runserver 0.0.0.0:8000

If everything is fine, you should get the following output:

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 18, 2023 - 13:09:49
Django version 4.1.5, using settings 'djangoapp.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.

Now, open your web browser and access your Django project using the URL http://django.example.com:8000/admin/. You will be redirected to the Django login page:

How to Install Django Python Web Framework on Ubuntu 22.04 linux ubuntu

Provide your admin username, password and click on the Login. You should see the Django dashboard in the following page:

How to Install Django Python Web Framework on Ubuntu 22.04 linux ubuntu

Now, go back to your terminal and press CTRL C to stop the Django development server.

Verify Django with Gunicorn

Next, you will also need to test whether the Gunicorn can serve the Django or not. You can start the Django using the Gunicorn server with the following command:

gunicorn --bind 0.0.0.0:8000 djangoapp.wsgi

If everything is fine, you should get the following output:

[2023-01-18 13:11:55  0000] [6268] [INFO] Starting gunicorn 20.1.0
[2023-01-18 13:11:55  0000] [6268] [INFO] Listening at: http://0.0.0.0:8000 (6268)
[2023-01-18 13:11:55  0000] [6268] [INFO] Using worker: sync
[2023-01-18 13:11:55  0000] [6269] [INFO] Booting worker with pid: 6269

Press CTRL C to stop the Gunicorn server.

Next, deactivate from Python virtual environment with the following command:

deactivate

Create a Systemd Service File for Gunicorn

Next, you will need to create a systemd service file for the Gunicorn to start and stop the Django application server.

You can create it with the following command:

nano /etc/systemd/system/gunicorn.socket

Add the following lines:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Save and close the file then create a service file for Gunicorn:

nano /etc/systemd/system/gunicorn.service

Add the following lines that match your Django project path:

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/var/www/html/djangoapp/
ExecStart=/var/www/html/djangoapp/djangoenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock          djangoapp.wsgi:application

[Install]
WantedBy=multi-user.target

Save and close the file then set proper permission to the Django project directory:

chown -R www-data:root /var/www/html/djangoapp

Next, reload the systemd daemon with the following command:

systemctl daemon-reload

Next, start the Gunicorn service and enable it to start at system reboot:

systemctl start gunicorn.socket
systemctl enable gunicorn.socket

Next, check the status of the Gunicorn using the command below:

systemctl status gunicorn.socket

You should get the following output:

? gunicorn.socket - gunicorn socket
     Loaded: loaded (/etc/systemd/system/gunicorn.socket; disabled; vendor preset: enabled)
     Active: active (listening) since Wed 2023-01-18 13:13:55 UTC; 17s ago
   Triggers: ? gunicorn.service
     Listen: /run/gunicorn.sock (Stream)
     CGroup: /system.slice/gunicorn.socket

Jan 18 13:13:55 ubuntu2204 systemd[1]: Listening on gunicorn socket.

Configure Nginx as a Reverse Proxy

Next, you will need to configure Nginx as a reverse proxy to serve the Django on port 80.

nano /etc/nginx/conf.d/django.conf

Add the following lines:

server {
     listen 80;
     server_name django.example.com;
    location = /favicon.ico { access_log off; log_not_found off; }


    location /static/ {
         root /var/www/html/djangoapp/djangoapp;
     }

    location / {
         include proxy_params;
         proxy_pass http://unix:/run/gunicorn.sock;
     }
}

Save and close the file then verify the Nginx for any configuration error:

nginx -t

You will get the following output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Finally, restart the Nginx service to apply the changes:

systemctl restart nginx

To check the Nginx status, run the following command.

systemctl status nginx

You will get the following output.

? nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-01-18 13:15:37 UTC; 6s ago
       Docs: man:nginx(8)
    Process: 7336 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 7337 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 7338 (nginx)
      Tasks: 3 (limit: 4579)
     Memory: 3.3M
        CPU: 29ms
     CGroup: /system.slice/nginx.service
             ??7338 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ??7339 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
             ??7340 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""

Jan 18 13:15:37 ubuntu2204 systemd[1]: Starting A high performance web server and a reverse proxy server...
Jan 18 13:15:37 ubuntu2204 systemd[1]: Started A high performance web server and a reverse proxy server.

Now, you can access the Django application using the URL http://django.example.com/admin. You can also access the Django application using the URL http://django.example.com/.

Conclusion

Congratulations! you have successfully installed a Django application with Gunicorn and Nginx as a reverse proxy on Ubuntu 22.04. You can now start deploying your Python application using the Django framework. Feel free to ask me if you have any questions.