feat: contact form and more edits
This commit is contained in:
+14
-1
@@ -1,6 +1,19 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import DownloadItem, FAQEntry
|
||||
from .models import ContactSubmission, DownloadItem, FAQEntry
|
||||
|
||||
|
||||
@admin.register(ContactSubmission)
|
||||
class ContactSubmissionAdmin(admin.ModelAdmin):
|
||||
list_display = ("name", "title", "email", "submitted_at", "is_read")
|
||||
list_filter = ("is_read", "submitted_at")
|
||||
search_fields = ("name", "title", "description", "email")
|
||||
list_editable = ("is_read",)
|
||||
readonly_fields = ("name", "title", "description", "email", "submitted_at")
|
||||
fieldsets = (
|
||||
(None, {"fields": ("name", "title", "email", "description")}),
|
||||
("Meta", {"fields": ("submitted_at", "is_read")}),
|
||||
)
|
||||
|
||||
|
||||
@admin.register(FAQEntry)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from django import forms
|
||||
|
||||
from .models import ContactSubmission
|
||||
|
||||
|
||||
class ContactForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ContactSubmission
|
||||
fields = ["name", "title", "description", "email"]
|
||||
widgets = {
|
||||
"name": forms.TextInput(
|
||||
attrs={"placeholder": "Your full name", "autocomplete": "name"}
|
||||
),
|
||||
"title": forms.TextInput(attrs={"placeholder": "Subject / topic"}),
|
||||
"description": forms.Textarea(
|
||||
attrs={"placeholder": "Write your message here…", "rows": 5}
|
||||
),
|
||||
"email": forms.EmailInput(
|
||||
attrs={
|
||||
"placeholder": "your@email.com (optional)",
|
||||
"autocomplete": "email",
|
||||
}
|
||||
),
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# Generated by Django 5.0.2 on 2026-05-04 09:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pages', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ContactSubmission',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=200)),
|
||||
('title', models.CharField(max_length=300)),
|
||||
('description', models.TextField()),
|
||||
('email', models.EmailField(blank=True, max_length=254)),
|
||||
('submitted_at', models.DateTimeField(auto_now_add=True)),
|
||||
('is_read', models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Contact Submission',
|
||||
'verbose_name_plural': 'Contact Submissions',
|
||||
'ordering': ['-submitted_at'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,6 +1,23 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class ContactSubmission(models.Model):
|
||||
name = models.CharField(max_length=200)
|
||||
title = models.CharField(max_length=300)
|
||||
description = models.TextField()
|
||||
email = models.EmailField(blank=True)
|
||||
submitted_at = models.DateTimeField(auto_now_add=True)
|
||||
is_read = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ["-submitted_at"]
|
||||
verbose_name = "Contact Submission"
|
||||
verbose_name_plural = "Contact Submissions"
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} — {self.title}"
|
||||
|
||||
|
||||
class FAQEntry(models.Model):
|
||||
question = models.CharField(max_length=500)
|
||||
answer = models.TextField()
|
||||
|
||||
@@ -27,14 +27,14 @@ class AboutViewTest(TestCase):
|
||||
class DownloadsViewTest(TestCase):
|
||||
def setUp(self):
|
||||
DownloadItem.objects.create(
|
||||
name="ViSERA Desktop",
|
||||
name="Radiuma Desktop",
|
||||
platform="windows",
|
||||
version="1.0",
|
||||
download_url="https://example.com/windows",
|
||||
is_active=True,
|
||||
)
|
||||
DownloadItem.objects.create(
|
||||
name="ViSERA Desktop",
|
||||
name="Radiuma Desktop",
|
||||
platform="macos",
|
||||
version="Coming Soon",
|
||||
download_url="#",
|
||||
|
||||
+46
-2
@@ -1,6 +1,12 @@
|
||||
import random
|
||||
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import render
|
||||
from django.views import View
|
||||
from django.views.generic import ListView, TemplateView
|
||||
|
||||
from .models import DownloadItem, FAQEntry
|
||||
from .forms import ContactForm
|
||||
from .models import ContactSubmission, DownloadItem, FAQEntry
|
||||
|
||||
|
||||
class HomeView(TemplateView):
|
||||
@@ -36,5 +42,43 @@ class FAQView(ListView):
|
||||
queryset = FAQEntry.objects.filter(is_active=True)
|
||||
|
||||
|
||||
class ContactView(TemplateView):
|
||||
class ContactView(View):
|
||||
template_name = "pages/contact.html"
|
||||
|
||||
def _new_captcha(self, request):
|
||||
a, b = random.randint(1, 9), random.randint(1, 9)
|
||||
request.session["captcha_answer"] = a + b
|
||||
return f"{a} + {b}"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return render(
|
||||
request,
|
||||
self.template_name,
|
||||
{"form": ContactForm(), "captcha_question": self._new_captcha(request)},
|
||||
)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = ContactForm(request.POST)
|
||||
expected = request.session.get("captcha_answer")
|
||||
captcha_question = self._new_captcha(request)
|
||||
|
||||
captcha_ok = False
|
||||
try:
|
||||
captcha_ok = int(request.POST.get("captcha_answer", "")) == expected
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
if form.is_valid() and captcha_ok:
|
||||
form.save()
|
||||
return JsonResponse({"success": True})
|
||||
|
||||
errors: dict = {}
|
||||
if not captcha_ok:
|
||||
errors["captcha"] = ["Incorrect answer — please try again."]
|
||||
errors.update(
|
||||
{field: [str(e) for e in errs] for field, errs in form.errors.items()}
|
||||
)
|
||||
return JsonResponse(
|
||||
{"success": False, "errors": errors, "captcha_question": captcha_question},
|
||||
status=400,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user