Django supports multiple relational database management systems (RDBMS) apart from SQLite, including PostgreSQL, MySQL, MariaDB, and Oracle. To switch from SQLite to another database, the database settings in settings.py
must be updated.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost', # Set to the server's IP or domain in production
'PORT': '5432', # Default PostgreSQL port
}
}
Before using PostgreSQL, install psycopg2
:
pip install psycopg2
For better performance, install psycopg2-binary
:
pip install psycopg2-binary
For MySQL or MariaDB, use the appropriate engine:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '3306', # Default MySQL/MariaDB port
}
}
pip install mysqlclient
For an alternative, use PyMySQL
:
pip install PyMySQL
Then, add this to __init__.py
in the project folder:
import pymysql
pymysql.install_as_MySQLdb()
After configuring the database, run:
python manage.py migrate
This creates necessary tables for Django’s built-in apps like authentication, sessions, and admin.
PostgreSQL User Creation
CREATE USER mydatabaseuser WITH PASSWORD 'mypassword';
ALTER ROLE mydatabaseuser SET client_encoding TO 'utf8';
ALTER ROLE mydatabaseuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE mydatabaseuser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE mydatabase TO mydatabaseuser;
MySQL User Creation
CREATE USER 'mydatabaseuser'@'localhost' IDENTIFIED BY 'mypassword';
GRANT ALL PRIVILEGES ON mydatabase.* TO 'mydatabaseuser'@'localhost';
FLUSH PRIVILEGES;
For a remote PostgreSQL database, set HOST
to the server’s IP or domain:
'HOST': 'db.example.com',
'PORT': '5432',
For a remote MySQL database:
'HOST': 'db.example.com',
'PORT': '3306',
Ensure the database server allows external connections by modifying pg_hba.conf
(PostgreSQL) or mysqld.cnf
(MySQL).
Hardcoding database credentials in settings.py
is insecure. Instead, use environment variables:
import os
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST', 'localhost'),
'PORT': os.getenv('DB_PORT', '5432'),
}
}
Set these variables in .env
:
DB_NAME=mydatabase
DB_USER=mydatabaseuser
DB_PASSWORD=mypassword
DB_HOST=localhost
DB_PORT=5432
Use django-environ
to manage .env
files:
pip install django-environ
Modify settings.py
:
import environ
env = environ.Env()
environ.Env.read_env()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('DB_NAME'),
'USER': env('DB_USER'),
'PASSWORD': env('DB_PASSWORD'),
'HOST': env('DB_HOST', default='localhost'),
'PORT': env('DB_PORT', default='5432'),
}
}
For better performance, use pgbouncer (PostgreSQL) or MySQL connection pooling.
Example with pgbouncer
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '6432', # pgbouncer default port
'CONN_MAX_AGE': 600, # Keep connection alive for 10 minutes
}
}
For MySQL:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/etc/mysql/my.cnf',
},
}
}
Django supports multiple databases using the DATABASES
dictionary.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'default_db',
'USER': 'default_user',
'PASSWORD': 'default_password',
'HOST': 'localhost',
'PORT': '5432',
},
'replica': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'replica_db',
'USER': 'replica_user',
'PASSWORD': 'replica_password',
'HOST': 'replica_host',
'PORT': '5432',
},
}
Define a database_router.py
:
class MyDatabaseRouter:
def db_for_read(self, model, **hints):
"""Send read queries to the replica database."""
return 'replica'
def db_for_write(self, model, **hints):
"""Send write queries to the default database."""
return 'default'
def allow_relation(self, obj1, obj2, **hints):
return True
def allow_migrate(self, db, app_label, model_name=None, **hints):
return True
Add this in settings.py
:
DATABASE_ROUTERS = ['myapp.database_router.MyDatabaseRouter']
While Django’s ORM is powerful, raw SQL can be used when necessary.
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM myapp_mymodel")
rows = cursor.fetchall()
cursor.execute("SELECT * FROM myapp_mymodel WHERE id = %s", [1])
PostgreSQL provides advanced features like JSON fields, full-text search, and GIS support.
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
metadata = models.JSONField()
from django.contrib.postgres.search import SearchVector
from myapp.models import Product
Product.objects.annotate(search=SearchVector('name')).filter(search='laptop')
class Product(models.Model):
name = models.CharField(max_length=255, db_index=True)
For GIN Index on JSON Fields:
from django.contrib.postgres.indexes import GinIndex
class Product(models.Model):
metadata = models.JSONField()
class Meta:
indexes = [GinIndex(fields=['metadata'])]