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:
@@ -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}"
|
||||
|
||||
|
||||
9
backend/advertisement/serializer.py
Normal file
9
backend/advertisement/serializer.py
Normal 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"]
|
||||
@@ -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,
|
||||
)
|
||||
6
backend/advertisement/templates/email/contact_me.html
Normal file
6
backend/advertisement/templates/email/contact_me.html
Normal 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>
|
||||
15
backend/advertisement/urls.py
Normal file
15
backend/advertisement/urls.py
Normal 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)),
|
||||
]
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user