mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 02:51:12 -05:00
- 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.
253 lines
9.0 KiB
Python
253 lines
9.0 KiB
Python
"""
|
|
Signal handlers for automatic search vector updates.
|
|
|
|
These signals ensure search vectors stay synchronized with model changes,
|
|
eliminating the need for manual re-indexing.
|
|
|
|
Signal handlers are only active when using PostgreSQL with PostGIS backend.
|
|
"""
|
|
from django.db.models.signals import post_save, pre_save
|
|
from django.dispatch import receiver
|
|
from django.conf import settings
|
|
from django.contrib.postgres.search import SearchVector
|
|
|
|
from apps.entities.models import Company, RideModel, Park, Ride
|
|
|
|
# Only register signals if using PostgreSQL with PostGIS
|
|
_using_postgis = 'postgis' in settings.DATABASES['default']['ENGINE']
|
|
|
|
|
|
if _using_postgis:
|
|
|
|
# ==========================================
|
|
# Company Signals
|
|
# ==========================================
|
|
|
|
@receiver(post_save, sender=Company)
|
|
def update_company_search_vector(sender, instance, created, **kwargs):
|
|
"""
|
|
Update search vector when company is created or updated.
|
|
|
|
Search vector includes:
|
|
- name (weight A)
|
|
- description (weight B)
|
|
"""
|
|
# Update the company's own search vector
|
|
Company.objects.filter(pk=instance.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
|
|
@receiver(pre_save, sender=Company)
|
|
def check_company_name_change(sender, instance, **kwargs):
|
|
"""
|
|
Track if company name is changing to trigger cascading updates.
|
|
|
|
Stores the old name on the instance for use in post_save signal.
|
|
"""
|
|
if instance.pk:
|
|
try:
|
|
old_instance = Company.objects.get(pk=instance.pk)
|
|
instance._old_name = old_instance.name
|
|
except Company.DoesNotExist:
|
|
instance._old_name = None
|
|
else:
|
|
instance._old_name = None
|
|
|
|
|
|
@receiver(post_save, sender=Company)
|
|
def cascade_company_name_updates(sender, instance, created, **kwargs):
|
|
"""
|
|
When company name changes, update search vectors for related objects.
|
|
|
|
Updates:
|
|
- All RideModels from this manufacturer
|
|
- All Rides from this manufacturer
|
|
"""
|
|
# Skip if this is a new company or name hasn't changed
|
|
if created or not hasattr(instance, '_old_name'):
|
|
return
|
|
|
|
old_name = getattr(instance, '_old_name', None)
|
|
if old_name == instance.name:
|
|
return
|
|
|
|
# Update all RideModels from this manufacturer
|
|
ride_models = RideModel.objects.filter(manufacturer=instance)
|
|
for ride_model in ride_models:
|
|
RideModel.objects.filter(pk=ride_model.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('manufacturer__name', weight='A', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
# Update all Rides from this manufacturer
|
|
rides = Ride.objects.filter(manufacturer=instance)
|
|
for ride in rides:
|
|
Ride.objects.filter(pk=ride.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('park__name', weight='A', config='english') +
|
|
SearchVector('manufacturer__name', weight='B', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
|
|
# ==========================================
|
|
# Park Signals
|
|
# ==========================================
|
|
|
|
@receiver(post_save, sender=Park)
|
|
def update_park_search_vector(sender, instance, created, **kwargs):
|
|
"""
|
|
Update search vector when park is created or updated.
|
|
|
|
Search vector includes:
|
|
- name (weight A)
|
|
- description (weight B)
|
|
"""
|
|
# Update the park's own search vector
|
|
Park.objects.filter(pk=instance.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
|
|
@receiver(pre_save, sender=Park)
|
|
def check_park_name_change(sender, instance, **kwargs):
|
|
"""
|
|
Track if park name is changing to trigger cascading updates.
|
|
|
|
Stores the old name on the instance for use in post_save signal.
|
|
"""
|
|
if instance.pk:
|
|
try:
|
|
old_instance = Park.objects.get(pk=instance.pk)
|
|
instance._old_name = old_instance.name
|
|
except Park.DoesNotExist:
|
|
instance._old_name = None
|
|
else:
|
|
instance._old_name = None
|
|
|
|
|
|
@receiver(post_save, sender=Park)
|
|
def cascade_park_name_updates(sender, instance, created, **kwargs):
|
|
"""
|
|
When park name changes, update search vectors for related rides.
|
|
|
|
Updates:
|
|
- All Rides in this park
|
|
"""
|
|
# Skip if this is a new park or name hasn't changed
|
|
if created or not hasattr(instance, '_old_name'):
|
|
return
|
|
|
|
old_name = getattr(instance, '_old_name', None)
|
|
if old_name == instance.name:
|
|
return
|
|
|
|
# Update all Rides in this park
|
|
rides = Ride.objects.filter(park=instance)
|
|
for ride in rides:
|
|
Ride.objects.filter(pk=ride.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('park__name', weight='A', config='english') +
|
|
SearchVector('manufacturer__name', weight='B', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
|
|
# ==========================================
|
|
# RideModel Signals
|
|
# ==========================================
|
|
|
|
@receiver(post_save, sender=RideModel)
|
|
def update_ride_model_search_vector(sender, instance, created, **kwargs):
|
|
"""
|
|
Update search vector when ride model is created or updated.
|
|
|
|
Search vector includes:
|
|
- name (weight A)
|
|
- manufacturer__name (weight A)
|
|
- description (weight B)
|
|
"""
|
|
RideModel.objects.filter(pk=instance.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('manufacturer__name', weight='A', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
|
|
@receiver(pre_save, sender=RideModel)
|
|
def check_ride_model_manufacturer_change(sender, instance, **kwargs):
|
|
"""
|
|
Track if ride model manufacturer is changing.
|
|
|
|
Stores the old manufacturer on the instance for use in post_save signal.
|
|
"""
|
|
if instance.pk:
|
|
try:
|
|
old_instance = RideModel.objects.get(pk=instance.pk)
|
|
instance._old_manufacturer = old_instance.manufacturer
|
|
except RideModel.DoesNotExist:
|
|
instance._old_manufacturer = None
|
|
else:
|
|
instance._old_manufacturer = None
|
|
|
|
|
|
# ==========================================
|
|
# Ride Signals
|
|
# ==========================================
|
|
|
|
@receiver(post_save, sender=Ride)
|
|
def update_ride_search_vector(sender, instance, created, **kwargs):
|
|
"""
|
|
Update search vector when ride is created or updated.
|
|
|
|
Search vector includes:
|
|
- name (weight A)
|
|
- park__name (weight A)
|
|
- manufacturer__name (weight B)
|
|
- description (weight B)
|
|
"""
|
|
Ride.objects.filter(pk=instance.pk).update(
|
|
search_vector=(
|
|
SearchVector('name', weight='A', config='english') +
|
|
SearchVector('park__name', weight='A', config='english') +
|
|
SearchVector('manufacturer__name', weight='B', config='english') +
|
|
SearchVector('description', weight='B', config='english')
|
|
)
|
|
)
|
|
|
|
|
|
@receiver(pre_save, sender=Ride)
|
|
def check_ride_relationships_change(sender, instance, **kwargs):
|
|
"""
|
|
Track if ride park or manufacturer are changing.
|
|
|
|
Stores old values on the instance for use in post_save signal.
|
|
"""
|
|
if instance.pk:
|
|
try:
|
|
old_instance = Ride.objects.get(pk=instance.pk)
|
|
instance._old_park = old_instance.park
|
|
instance._old_manufacturer = old_instance.manufacturer
|
|
except Ride.DoesNotExist:
|
|
instance._old_park = None
|
|
instance._old_manufacturer = None
|
|
else:
|
|
instance._old_park = None
|
|
instance._old_manufacturer = None
|