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

@@ -1,3 +1,14 @@
from django.db import models
# Create your models here.
class ContactMe(models.Model):
client_email = models.EmailField()
content = models.TextField()
sent_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Email to {self.client_email} sent at {self.sent_at}"

View File

@@ -0,0 +1,9 @@
from rest_framework import serializers
from .models import ContactMe
class ContactMeSerializer(serializers.ModelSerializer):
class Meta:
model = ContactMe
fields = ["id", "client_email", "content", "sent_at"]
read_only_fields = ["id", "sent_at"]

View File

@@ -1,2 +1,17 @@
#udělat zasílaní reklamních emailů uživatelům.
#newletter --> když se vytvoří nový record s reklamou email se uloží pomocí zaškrtnutí tlačítka v záznamu
from account.tasks import send_email_with_context
from configuration.models import SiteConfiguration
from celery import shared_task
@shared_task
def send_contact_me_email_task(client_email, message_content):
context = {
"client_email": client_email,
"message_content": message_content
}
send_email_with_context(
recipients=SiteConfiguration.get_solo().contact_email,
subject="Poptávka z kontaktního formuláře!!!",
template_path="email/contact_me.html",
context=context,
)

View File

@@ -0,0 +1,6 @@
<h2 style="margin:0 0 12px 0; font-family:Arial, Helvetica, sans-serif;">Nová zpráva z kontaktního formuláře</h2>
<div style="border: 1px solid #e5e7eb; border-radius: 8px; padding: 16px; font-family:Arial, Helvetica, sans-serif;">
<p><span style="font-weight:600;">Email odesílatele:</span> {{ client_email }}</p>
<p style="font-weight:600;">Zpráva:</p>
<pre style="white-space: pre-wrap; word-wrap: break-word;">{{ message_content }}</pre>
</div>

View File

@@ -0,0 +1,15 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ContactMePublicView, ContactMeAdminViewSet
router = DefaultRouter()
router.register(r"contact-messages", ContactMeAdminViewSet, basename="contactme")
urlpatterns = [
# Public endpoint
path("contact-me/", ContactMePublicView.as_view(), name="contact-me"),
# Admin endpoints
path("", include(router.urls)),
]

View File

@@ -1,3 +1,46 @@
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, viewsets
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.authentication import SessionAuthentication
from .models import ContactMe
from .serializer import ContactMeSerializer
from .tasks import send_contact_me_email_task
class ContactMePublicView(APIView):
permission_classes = [AllowAny]
# Avoid CSRF for public endpoint by disabling SessionAuthentication
authentication_classes = []
def post(self, request):
email = request.data.get("email")
message = request.data.get("message")
honeypot = request.data.get("hp") # hidden honeypot field
# If honeypot is filled, pretend success without processing
if honeypot:
return Response({"status": "ok"}, status=status.HTTP_200_OK)
if not email or not message:
return Response({"detail": "Missing email or message."}, status=status.HTTP_400_BAD_REQUEST)
# Save to DB
cm = ContactMe.objects.create(client_email=email, content=message)
# Send email via Celery task
try:
send_contact_me_email_task.delay(email, message)
except Exception:
# Fallback to direct call if Celery is not running in DEV
send_contact_me_email_task(email, message)
return Response({"id": cm.id, "status": "queued"}, status=status.HTTP_201_CREATED)
class ContactMeAdminViewSet(viewsets.ModelViewSet):
queryset = ContactMe.objects.all().order_by("-sent_at")
serializer_class = ContactMeSerializer
permission_classes = [IsAdminUser]
# Create your views here.