Refactor email system and add contact form backend

Refactored email sending to use a single HTML template with a base layout, removed plain text email templates, and updated all related backend logic. Introduced a new ContactMe model, serializer, Celery task, and API endpoints for handling contact form submissions, including email notifications. Renamed ShopConfiguration to SiteConfiguration throughout the backend for consistency. Updated frontend to remove unused components, add a new Services section, and adjust navigation and contact form integration.
This commit is contained in:
2025-12-12 01:52:41 +01:00
parent df83288591
commit 564418501c
34 changed files with 433 additions and 327 deletions

View File

@@ -6,14 +6,13 @@ class ConfigurationConfig(AppConfig):
name = 'configuration'
def ready(self):
"""Ensure the ShopConfiguration singleton exists at startup.
"""Ensure the SiteConfiguration singleton exists at startup.
Wrapped in broad DB error handling so that commands like
makemigrations/migrate don't fail when the table does not yet exist.
"""
try:
from .models import ShopConfiguration # local import to avoid premature app registry access
ShopConfiguration.get_solo() # creates if missing
from .models import SiteConfiguration # local import to avoid premature app registry access
SiteConfiguration.get_solo() # creates if missing
except (OperationalError, ProgrammingError):
# DB not ready (e.g., before initial migrate); ignore silently

View File

@@ -2,7 +2,7 @@ from django.db import models
# Create your models here.
class ShopConfiguration(models.Model):
class SiteConfiguration(models.Model):
name = models.CharField(max_length=100, default="Shop name", unique=True)
logo = models.ImageField(upload_to='shop_logos/', blank=True, null=True)

View File

@@ -1,10 +1,10 @@
from rest_framework import serializers
from .models import ShopConfiguration
from .models import SiteConfiguration
class ShopConfigurationAdminSerializer(serializers.ModelSerializer):
class SiteConfigurationAdminSerializer(serializers.ModelSerializer):
class Meta:
model = ShopConfiguration
model = SiteConfiguration
fields = [
"id",
"name",
@@ -29,9 +29,9 @@ class ShopConfigurationAdminSerializer(serializers.ModelSerializer):
]
class ShopConfigurationPublicSerializer(serializers.ModelSerializer):
class SiteConfigurationPublicSerializer(serializers.ModelSerializer):
class Meta:
model = ShopConfiguration
model = SiteConfiguration
# Expose only non-sensitive fields
fields = [
"id",

View File

@@ -1,8 +1,7 @@
from rest_framework.routers import DefaultRouter
from .views import ShopConfigurationAdminViewSet, ShopConfigurationPublicViewSet
from .views import SiteConfigurationAdminViewSet, SiteConfigurationPublicViewSet
router = DefaultRouter()
router.register(r"admin/shop-configuration", ShopConfigurationAdminViewSet, basename="shop-config-admin")
router.register(r"public/shop-configuration", ShopConfigurationPublicViewSet, basename="shop-config-public")
router.register(r"admin/shop-configuration", SiteConfigurationAdminViewSet, basename="shop-config-admin")
router.register(r"public/shop-configuration", SiteConfigurationPublicViewSet, basename="shop-config-public")
urlpatterns = router.urls

View File

@@ -1,25 +1,25 @@
from rest_framework import viewsets, mixins
from rest_framework.permissions import IsAdminUser, AllowAny
from .models import ShopConfiguration
from .models import SiteConfiguration
from .serializers import (
ShopConfigurationAdminSerializer,
ShopConfigurationPublicSerializer,
SiteConfigurationAdminSerializer,
SiteConfigurationPublicSerializer,
)
class _SingletonQuerysetMixin:
def get_queryset(self):
return ShopConfiguration.objects.filter(pk=1)
return SiteConfiguration.objects.filter(pk=1)
def get_object(self):
return ShopConfiguration.get_solo()
return SiteConfiguration.get_solo()
class ShopConfigurationAdminViewSet(_SingletonQuerysetMixin, viewsets.ModelViewSet):
class SiteConfigurationAdminViewSet(_SingletonQuerysetMixin, viewsets.ModelViewSet):
permission_classes = [IsAdminUser]
serializer_class = ShopConfigurationAdminSerializer
serializer_class = SiteConfigurationAdminSerializer
class ShopConfigurationPublicViewSet(_SingletonQuerysetMixin, viewsets.ReadOnlyModelViewSet):
class SiteConfigurationPublicViewSet(_SingletonQuerysetMixin, viewsets.ReadOnlyModelViewSet):
permission_classes = [AllowAny]
serializer_class = ShopConfigurationPublicSerializer
serializer_class = SiteConfigurationPublicSerializer