Originally published as a gist for Ubuntu 16.04 and Django 1.9. Updated for Ubuntu 22.04+ and Django 5.x with Python 3.
Table of Contents
- Introduction
- Prerequisites
- System Setup
- PostgreSQL Installation and Configuration
- Python Environment Setup
- Django Installation and Project Creation
- Database Configuration
- Running Your Application
- What’s Changed Since 2016
- Next Steps
Introduction
Setting up a Django web application with PostgreSQL as the database backend is a fundamental skill for Python web developers. This guide walks you through the complete process from a fresh Ubuntu installation to a running Django application with PostgreSQL.
What you’ll learn:
- How to install and configure PostgreSQL
- How to set up a proper Python development environment
- How to create and configure a Django project
- Best practices for database connection management
- Modern approaches using virtual environments
Prerequisites
Before we begin, you’ll need:
- Ubuntu 22.04 LTS or later (the concepts apply to most Debian-based systems)
- Terminal access with sudo privileges
- Basic familiarity with command-line operations
- At least 4GB RAM and 20GB disk space recommended
Note: This guide assumes a fresh or relatively clean Ubuntu installation. If you’re using a different Linux distribution, package names and commands may vary slightly.
System Setup
Update Your System
Always start with an up-to-date system:
sudo apt update
sudo apt upgrade -y
Optional: Desktop Environment
If you’re setting up a development VM and want a lightweight desktop:
# Optional: Install Xubuntu desktop
sudo apt install xubuntu-desktop
# Optional: Remove default Ubuntu desktop to save resources
sudo apt remove ubuntu-desktop
sudo apt autoremove
PostgreSQL Installation and Configuration
Install PostgreSQL and Dependencies
Install PostgreSQL along with the necessary development libraries:
sudo apt install postgresql postgresql-contrib libpq-dev python3-dev
What gets installed:
postgresql- The database serverpostgresql-contrib- Additional utilities and extensionslibpq-dev- PostgreSQL C library headers (needed for psycopg2)python3-dev- Python development headers (needed for compiling Python packages)
Understanding PostgreSQL Users
During installation, PostgreSQL creates an operating system user called postgres which has administrative privileges. We’ll use this user to set up our database.
Create a Database User
You have two approaches:
Option 1: Create a PostgreSQL superuser matching your OS username
sudo -u postgres createuser -s $USER
This creates a PostgreSQL user with the same name as your current OS user, making subsequent commands simpler.
Option 2: Use the postgres user directly
sudo -u postgres psql
This opens the PostgreSQL interactive terminal.
Create Your Database
Using the command line:
createdb -U $USER --locale=en_US.utf-8 -E utf-8 -O $USER myprojectdb -T template0
Or using the PostgreSQL shell:
CREATE DATABASE myprojectdb;
Parameters explained:
--locale=en_US.utf-8- Sets the database locale-E utf-8- Sets UTF-8 encoding (supports international characters)-O $USER- Sets the database owner-T template0- Uses clean template (recommended for custom encoding)
Create a Database User (if needed)
If you didn’t create a superuser earlier, create a specific user for your project:
-- In the PostgreSQL shell (psql)
CREATE USER myprojectuser WITH PASSWORD 'your_secure_password_here';
GRANT ALL PRIVILEGES ON DATABASE myprojectdb TO myprojectuser;
Security tip: Use a strong password. Consider using a password manager to generate and store it.
Grant Schema Privileges (Django 3.2+)
For Django 3.2 and later, you need to grant schema privileges:
\c myprojectdb
GRANT ALL ON SCHEMA public TO myprojectuser;
Exit the PostgreSQL shell:
\q
Python Environment Setup
Install Python and pip
Ubuntu 22.04 comes with Python 3.10+, but ensure you have pip and venv:
sudo apt install python3-pip python3-venv
Create a Virtual Environment
Why use virtual environments?
- Isolates project dependencies
- Prevents conflicts between projects
- Makes deployment easier
- Allows different Python/package versions per project
Create a virtual environment for your project:
# Create a directory for your project
mkdir ~/myproject
cd ~/myproject
# Create a virtual environment
python3 -m venv venv
# Activate the virtual environment
source venv/bin/activate
Your terminal prompt should now show (venv) indicating the virtual environment is active.
Upgrade pip and Install Wheel
pip install --upgrade pip wheel setuptools
Django Installation and Project Creation
Install Django and psycopg2
# Install Django (latest stable version)
pip install django
# Install PostgreSQL adapter
pip install psycopg2-binary
Note: psycopg2-binary is easier to install but psycopg2 is recommended for production. For production, use:
pip install psycopg2
Verify Installation
django-admin --version
You should see something like 5.0.1 or whatever the current Django version is.
Create Your Django Project
django-admin startproject myproject .
Note the dot (.) at the end - this creates the project in the current directory instead of creating a nested directory.
Your directory structure should now look like:
~/myproject/
├── venv/
├── myproject/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── asgi.py
│ └── wsgi.py
└── manage.py
Database Configuration
Configure Django Settings
Open the settings file:
nano ~/myproject/myproject/settings.py
Or use your preferred editor (vim, VSCode, etc.)
Update ALLOWED_HOSTS
Find the ALLOWED_HOSTS line and update it:
# For development
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
# For production, add your domain/IP
# ALLOWED_HOSTS = ['example.com', 'www.example.com', '1.2.3.4']
Configure Database Connection
Find the DATABASES section and replace it with:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myprojectdb',
'USER': 'myprojectuser',
'PASSWORD': 'your_secure_password_here',
'HOST': 'localhost',
'PORT': '5432',
}
}
Security Best Practice: Don’t hardcode passwords in settings.py. Use environment variables:
import os
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'myprojectdb'),
'USER': os.environ.get('DB_USER', 'myprojectuser'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
Then set environment variables:
export DB_PASSWORD='your_secure_password_here'
Or use python-decouple or django-environ for better environment management.
Additional Recommended Settings
While you’re in settings.py, consider these additions:
# Timezone
TIME_ZONE = 'America/New_York' # Adjust to your timezone
# Static files (for production)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# Security settings (for production)
# SECURE_SSL_REDIRECT = True
# SESSION_COOKIE_SECURE = True
# CSRF_COOKIE_SECURE = True
Running Your Application
Apply Database Migrations
Run Django’s initial migrations to create necessary tables:
cd ~/myproject
python manage.py makemigrations
python manage.py migrate
You should see output showing tables being created.
Create a Superuser
Create an admin account:
python manage.py createsuperuser
Follow the prompts to set:
- Username
- Email address (optional)
- Password (enter twice)
Start the Development Server
python manage.py runserver 0.0.0.0:8000
Access your application:
- Main site:
http://localhost:8000/ - Admin interface:
http://localhost:8000/admin/
Log in with your superuser credentials.
Running the Server in the Background
For development, you might want the server running while you work:
Using screen:
screen -S django-dev
python manage.py runserver 0.0.0.0:8000
# Press Ctrl+A then D to detach
# Reattach with: screen -r django-dev
Using tmux (recommended):
tmux new -s django-dev
python manage.py runserver 0.0.0.0:8000
# Press Ctrl+B then D to detach
# Reattach with: tmux attach -t django-dev
What’s Changed Since 2016
If you’re coming from my original 2016 gist, here are the major updates:
Python 2.7 → Python 3.10+
- Python 2 reached end-of-life in 2020
- All modern Django development uses Python 3
- Syntax changes:
printis now a function, string handling improved
Django 1.9 → Django 5.0
- Async support - Django now has native async views and ORM operations
- Improved admin - Better UI and customization options
- Better security defaults - More secure out of the box
- Path routing - New
path()function replaces old regex patterns - Type hints - Better IDE support and code completion
Ubuntu 16.04 → Ubuntu 22.04+
- Python 3 by default - No need to specify python3
- Systemd everywhere - Different service management
- Better security - AppArmor, improved firewall defaults
Development Practices
- Virtual environments are mandatory - No more global pip installs
- Environment variables - Don’t hardcode secrets
- Docker is common - Consider containerization for production
- CI/CD pipelines - Automated testing and deployment
Database
psycopg2-binaryvspsycopg2distinction- Connection pooling is more important at scale
- PostgreSQL 14+ has significant performance improvements
Next Steps
Now that you have a working Django application:
- Create your first app:
python manage.py startapp myapp -
Define models in
myapp/models.py -
Create views in
myapp/views.py -
Set up URLs in
myapp/urls.py -
Create templates in
myapp/templates/ - Run migrations after model changes:
python manage.py makemigrations python manage.py migrate
Learning Resources
- Official Django Tutorial: https://docs.djangoproject.com/en/stable/intro/tutorial01/
- Django Girls Tutorial: https://tutorial.djangogirls.org/
- Two Scoops of Django: Comprehensive best practices book
- Real Python: https://realpython.com/tutorials/django/
Production Deployment
For production environments, consider:
- Web servers: Nginx or Apache
- WSGI servers: Gunicorn or uWSGI
- Process managers: Systemd or Supervisor
- Static files: WhiteNoise or CDN
- Security: Let’s Encrypt for SSL
- Monitoring: Sentry for error tracking
- Containers: Docker for consistency
Save Your Requirements
Always maintain a requirements.txt:
pip freeze > requirements.txt
This allows easy recreation of your environment:
pip install -r requirements.txt
Troubleshooting
“pip: command not found”
sudo apt install python3-pip
“psycopg2 failed to build”
sudo apt install libpq-dev python3-dev
pip install psycopg2-binary
“FATAL: Peer authentication failed”
Edit /etc/postgresql/14/main/pg_hba.conf and change peer to md5 for local connections, then restart PostgreSQL:
sudo systemctl restart postgresql
Port 8000 already in use
# Find the process
lsof -i :8000
# Kill it
kill -9 <PID>
# Or use a different port
python manage.py runserver 8001
Conclusion
You now have a fully functional Django development environment with PostgreSQL! This setup provides a solid foundation for building web applications, from simple prototypes to complex production systems.
The key takeaways:
- Use virtual environments for every project
- Keep credentials out of version control
- Follow Django’s security best practices
- Stay updated with the latest Django LTS versions
- Test thoroughly before deploying to production
Happy coding! 🚀
Have questions or suggestions? Feel free to reach out or leave a comment below.
Related Posts:
- Setting Up Django with MySQL
- Django REST Framework Getting Started
- Deploying Django with Docker and PostgreSQL