Django Database Seeding
Create a fresh database on start Django application and seed it with default data is a common and recommended practice for ensuring a consistent development and testing environment. You can achieve this by creating a script that runs when your Docker container starts, which will handle the database setup and data seeding.
Here is a step-by-step guide on how to configure your Django project and Docker container to achieve this:
Step 1: Create a Custom Django Management Command to Seed Your Database
You can create a custom management command that reads data from a text file (like a CSV) and populates your database. This allows you to check your seed data into version control.
-
Structure your app for management commands: Inside one of your Django apps, create the following directory structure:
your_app/
├── management/
│ └── __init__.py
│ └── commands/
│ ├── __init__.py
│ └── seed_data.py
└── __init__.py
└── models.py
... -
Create the
seed_data.pycommand: This Python script will define the logic for seeding your database. Here's an example of how to read from a CSV file namedseed_data.csvand populate aYourModelmodel.In
your_app/management/commands/seed_data.py:import csv
from django.core.management.base import BaseCommand
from your_app.models import YourModel # Replace with your actual app and model
class Command(BaseCommand):
help = 'Seeds the database with initial data from a CSV file'
def handle(self, *args, **options):
# Define the path to your seed data file
seed_data_file = 'your_app/seed_data.csv'
# Clear existing data from the model to ensure a fresh start
YourModel.objects.all().delete()
self.stdout.write(self.style.SUCCESS('Successfully cleared existing data for YourModel.'))
try:
with open(seed_data_file, 'r') as file:
reader = csv.reader(file)
next(reader) # Skip the header row
for row in reader:
# Create a new model instance for each row in the CSV
YourModel.objects.create(
field1=row[0],
field2=row[1],
# Add other fields as necessary
)
self.stdout.write(self.style.SUCCESS('Successfully seeded the database.'))
except FileNotFoundError:
self.stdout.write(self.style.ERROR(f'Seed data file not found at: {seed_data_file}'))
except Exception as e:
self.stdout.write(self.style.ERROR(f'An error occurred while seeding the database: {e}')) -
Create your seed data file: Create a
seed_data.csvfile within your app directory. You can now easily track changes to this file with Git.your_app/seed_data.csv:field1,field2
value1,value2
another_value1,another_value2
Step 2: Create a Startup Script for Your Docker Container
Create a shell script that will be executed every time your container starts. This script will ensure the database is fresh and then seed it.
-
Create a script file: In the root of your project, create a file named
entrypoint.sh.entrypoint.sh:#!/bin/sh
# Exit immediately if a command exits with a non-zero status.
set -e
# It's a good practice to remove the old database file if it exists
# to ensure a completely fresh start, especially with SQLite.
if [ -f "db.sqlite3" ]; then
echo "Removing old database."
rm db.sqlite3
fi
# Run database migrations
echo "Running database migrations..."
python manage.py migrate
# Seed the database with initial data
echo "Seeding the database..."
python manage.py seed_data
# Start the Django development server
exec "$@" -
Make the script executable: Before building your Docker image, make sure this script is executable:
chmod +x entrypoint.sh
Step 3: Configure Your Dockerfile to Use the Startup Script
Modify your Dockerfile to copy the entrypoint.sh script and set it as the entrypoint.
Dockerfile:
# Start from a Python base image
FROM python:3.9-slim
# Set the working directory
WORKDIR /app
# Copy the requirements file and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application code
COPY . .
# Copy the entrypoint script and make it executable
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
# Set the entrypoint
ENTRYPOINT ["/app/entrypoint.sh"]
# The default command to run when the container starts
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
How It Works
- When you start your Docker container, the
ENTRYPOINTin yourDockerfilewill execute theentrypoint.shscript. - The script will first delete the old
db.sqlite3file if it exists. - Then,
python manage.py migratewill create a new, empty database with the correct schema. - After that, your custom
python manage.py seed_datacommand will run, populating the new database with the data from yourseed_data.csvfile. - Finally, the
CMDfrom yourDockerfile(ordocker-compose.yml) will be executed, starting your Django application.
This approach gives you a clean, predictable database state every time you start your container, with your seed data managed in a version-controlled text file as you wanted.