Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ src/django_project/*.sqlite3
src/django_project/*.log
src/django_project/local_test
src/django_project/tests

src/django_project/core/static/node_modules
src/django_project/core/static/package.json
src/django_project/core/static/package-lock.json
11 changes: 7 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
dependencies = [
"django~=5.2",
"django-braces",
"django-debug-toolbar",
"django-environ",
"django-extensions",
"django-filter",
"django-handyhelpers",
"django-handyhelpers==0.3.41",
"djangorestframework",
"djangorestframework-filters==1.0.0.dev0",
"drf-flex-fields",
"drf-spectacular",
"drf-renderer-xlsx",
"psycopg2-binary",
"whitenoise",
]
description = "Spokane Python Community"
dynamic = ["version"]
Expand All @@ -27,7 +26,6 @@ requires-python = ">=3.10"
dev = [
"bandit",
"coveralls",
"django-debug-toolbar",
"faker",
"isort",
"model-bakery",
Expand All @@ -43,6 +41,11 @@ dev = [
"types-requests",
"typing_extensions",
]
docker = [
"gunicorn",
"psycopg2-binary",
"whitenoise",
]


[tool.bandit]
Expand Down
13 changes: 11 additions & 2 deletions src/django_project/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool("DEBUG", True)
DEPLOYMENT_ENV = env.str("DEPLOYMENT_ENV", "local")


ALLOWED_HOSTS = env.str("ALLOWED_HOSTS", "127.0.0.1").split(",")
INTERNAL_IPS = env.str("INTERNAL_IPS", "127.0.0.1").split(",")
Expand All @@ -52,7 +54,6 @@
"django.contrib.messages",
"django.contrib.staticfiles",
# third party apps
"debug_toolbar",
"django_extensions",
"django_filters",
"drf_spectacular",
Expand All @@ -66,14 +67,22 @@

MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"debug_toolbar.middleware.DebugToolbarMiddleware",
]
if DEPLOYMENT_ENV in ["local", "dev"]:
INSTALLED_APPS += [
"debug_toolbar", # pragma: no cover
]
MIDDLEWARE += [
"debug_toolbar.middleware.DebugToolbarMiddleware", # pragma: no cover
]


ROOT_URLCONF = "core.urls"

Expand Down
42 changes: 0 additions & 42 deletions src/django_project/core/static/package-lock.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/django_project/core/urls/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
path("", include("web.urls", namespace="web")),
]

if settings.DEBUG:
if settings.DEBUG and settings.DEPLOYMENT_ENV in ["local", "dev"]:
urlpatterns.append(
path("__debug__/", include("debug_toolbar.urls")),
) # pragma: no cover
32 changes: 32 additions & 0 deletions src/django_project/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

# Exit immediately if a command exits with a non-zero status
set -e

# Function to wait for the database to be ready
wait_for_db() {
echo "Waiting for database to be ready..."
until nc -z "$DB_HOST" "$DB_PORT"; do
echo "Database is unavailable - sleeping"
sleep 1
done
echo "Database is up - continuing"
}

# Wait for the database to be ready
wait_for_db

# Run migrations
echo "Running migrations..."
python manage.py migrate

# Create superuser
echo "Creating superuser..."
python manage.py add_superuser --username $DJANGO_ADMIN_USERNAME --group admin --password $DJANGO_ADMIN_PASSWORD

# Collect static files
echo "Collecting static files..."
python manage.py collectstatic --noinput

# Launch gunicorn
gunicorn core.wsgi:application --bind 0.0.0.0:8000 --workers 3
5 changes: 3 additions & 2 deletions src/django_project/web/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.2.4 on 2025-07-27 20:48
# Generated by Django 5.2.4 on 2025-07-29 22:16

import django.db.models.deletion
from django.db import migrations, models
Expand All @@ -21,6 +21,7 @@ class Migration(migrations.Migration):
("end_date_time", models.DateTimeField()),
("location", models.CharField(blank=True, max_length=256, null=True)),
("description", models.TextField(blank=True, null=True)),
("url", models.URLField(blank=True, null=True)),
],
options={
"ordering": ["-start_date_time"],
Expand All @@ -37,7 +38,7 @@ class Migration(migrations.Migration):
("title", models.CharField(max_length=128)),
("description", models.TextField()),
(
"target_audience",
"skill_level",
models.CharField(
choices=[
("all", "All Levels"),
Expand Down
17 changes: 0 additions & 17 deletions src/django_project/web/migrations/0002_event_url.py

This file was deleted.

This file was deleted.

45 changes: 45 additions & 0 deletions src/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# === STAGE 1: Build dependencies in a virtual environment ===
FROM python:3.12-alpine AS builder

WORKDIR /app

# Install build dependencies
RUN apk add --no-cache \
gcc \
musl-dev \
libffi-dev \
openssl-dev

COPY pyproject.toml /app/

# Install pip-tools and create a virtual environment
RUN pip install --upgrade pip
RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH"
RUN pip install .[docker]


# === STAGE 2: Runtime with only necessary files ===
FROM python:3.12-alpine

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

# Install minimal runtime dependencies
RUN apk add --no-cache libffi openssl libstdc++

# Copy the virtual environment from the builder stage
COPY --from=builder /venv /venv

# Add the virtual environment's Python to the PATH
ENV PATH="/venv/bin:$PATH"

# Copy Django project code
COPY src/django_project /app/
RUN chmod +x /app/entrypoint.sh

EXPOSE 8000

CMD ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]
31 changes: 31 additions & 0 deletions src/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: '3.9'

services:
django:
image: spokanepython-django:latest
container_name: django
build:
context: ../..
dockerfile: src/docker/Dockerfile
env_file:
- ../envs/.env.docker-compose
command: ./entrypoint.sh
ports:
- "8000:8000"
depends_on:
- db
restart: unless-stopped

db:
image: postgres:17
container_name: postgres
volumes:
- spokanepython_postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
env_file:
- ../envs/.env.docker-compose
restart: unless-stopped

volumes:
spokanepython_postgres:
1 change: 0 additions & 1 deletion src/envs/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ PROJECT_NAME="myproject"
PROJECT_DESCRIPTION="my super awesome project powered, in part, by amazing code provided by DjangoAddicts."
PROJECT_VERSION="0.0.1"
PROJECT_SOURCE="https://github.com/djangoaddicts"
PYGWALKER_THEME="light"