Add email templates for user notifications and account management

- Created a base email template (base.html) for consistent styling across all emails.
- Added moderation approval email template (moderation_approved.html) to notify users of approved submissions.
- Added moderation rejection email template (moderation_rejected.html) to inform users of required changes for their submissions.
- Created password reset email template (password_reset.html) for users requesting to reset their passwords.
- Developed a welcome email template (welcome.html) to greet new users and provide account details and tips for using ThrillWiki.
This commit is contained in:
pacnpal
2025-11-08 15:34:04 -05:00
parent 9c46ef8b03
commit d6ff4cc3a3
335 changed files with 61926 additions and 73 deletions

View File

@@ -0,0 +1,35 @@
# Generated by Django 4.2.8 on 2025-11-08 17:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("entities", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="park",
name="latitude",
field=models.DecimalField(
blank=True,
decimal_places=7,
help_text="Latitude coordinate. Primary in local dev, use location_point in production.",
max_digits=10,
null=True,
),
),
migrations.AlterField(
model_name="park",
name="longitude",
field=models.DecimalField(
blank=True,
decimal_places=7,
help_text="Longitude coordinate. Primary in local dev, use location_point in production.",
max_digits=10,
null=True,
),
),
]

View File

@@ -0,0 +1,141 @@
# Generated migration for Phase 2 - GIN Index Optimization
from django.db import migrations, connection
from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import SearchVector
def is_postgresql():
"""Check if the database backend is PostgreSQL/PostGIS."""
return 'postgis' in connection.vendor or 'postgresql' in connection.vendor
def populate_search_vectors(apps, schema_editor):
"""Populate search_vector fields for all existing records."""
if not is_postgresql():
return
# Get models
Company = apps.get_model('entities', 'Company')
RideModel = apps.get_model('entities', 'RideModel')
Park = apps.get_model('entities', 'Park')
Ride = apps.get_model('entities', 'Ride')
# Update Company search vectors
Company.objects.update(
search_vector=(
SearchVector('name', weight='A') +
SearchVector('description', weight='B')
)
)
# Update RideModel search vectors
RideModel.objects.update(
search_vector=(
SearchVector('name', weight='A') +
SearchVector('manufacturer__name', weight='A') +
SearchVector('description', weight='B')
)
)
# Update Park search vectors
Park.objects.update(
search_vector=(
SearchVector('name', weight='A') +
SearchVector('description', weight='B')
)
)
# Update Ride search vectors
Ride.objects.update(
search_vector=(
SearchVector('name', weight='A') +
SearchVector('park__name', weight='A') +
SearchVector('manufacturer__name', weight='B') +
SearchVector('description', weight='B')
)
)
def reverse_search_vectors(apps, schema_editor):
"""Clear search_vector fields for all records."""
if not is_postgresql():
return
# Get models
Company = apps.get_model('entities', 'Company')
RideModel = apps.get_model('entities', 'RideModel')
Park = apps.get_model('entities', 'Park')
Ride = apps.get_model('entities', 'Ride')
# Clear all search vectors
Company.objects.update(search_vector=None)
RideModel.objects.update(search_vector=None)
Park.objects.update(search_vector=None)
Ride.objects.update(search_vector=None)
def add_gin_indexes(apps, schema_editor):
"""Add GIN indexes on search_vector fields (PostgreSQL only)."""
if not is_postgresql():
return
# Use raw SQL to add GIN indexes
with schema_editor.connection.cursor() as cursor:
cursor.execute("""
CREATE INDEX IF NOT EXISTS entities_company_search_idx
ON entities_company USING gin(search_vector);
""")
cursor.execute("""
CREATE INDEX IF NOT EXISTS entities_ridemodel_search_idx
ON entities_ridemodel USING gin(search_vector);
""")
cursor.execute("""
CREATE INDEX IF NOT EXISTS entities_park_search_idx
ON entities_park USING gin(search_vector);
""")
cursor.execute("""
CREATE INDEX IF NOT EXISTS entities_ride_search_idx
ON entities_ride USING gin(search_vector);
""")
def remove_gin_indexes(apps, schema_editor):
"""Remove GIN indexes (PostgreSQL only)."""
if not is_postgresql():
return
# Use raw SQL to drop GIN indexes
with schema_editor.connection.cursor() as cursor:
cursor.execute("DROP INDEX IF EXISTS entities_company_search_idx;")
cursor.execute("DROP INDEX IF EXISTS entities_ridemodel_search_idx;")
cursor.execute("DROP INDEX IF EXISTS entities_park_search_idx;")
cursor.execute("DROP INDEX IF EXISTS entities_ride_search_idx;")
class Migration(migrations.Migration):
"""
Phase 2 Migration: Add GIN indexes for search optimization.
This migration:
1. Adds GIN indexes on search_vector fields for optimal full-text search
2. Populates search vectors for all existing database records
3. Is PostgreSQL-specific and safe for SQLite environments
"""
dependencies = [
('entities', '0002_alter_park_latitude_alter_park_longitude'),
]
operations = [
# First, populate search vectors for existing records
migrations.RunPython(
populate_search_vectors,
reverse_search_vectors,
),
# Add GIN indexes for each model's search_vector field
migrations.RunPython(
add_gin_indexes,
remove_gin_indexes,
),
]