Coverage for website/forms/PostForm.py: 81%
36 statements
« prev ^ index » next coverage.py v7.5.0, created at 2025-09-13 15:29 -0300
« prev ^ index » next coverage.py v7.5.0, created at 2025-09-13 15:29 -0300
1from django import forms
3from website.models.PostModel import Post
4from website.utils.sanitizer import sanitize_html
7class PostForm(forms.ModelForm):
8 """Enhanced form for creating and editing blog posts with rich text editor"""
10 class Meta:
11 model = Post
12 fields = ["title", "url_slug", "meta_description", "text"]
13 widgets = {
14 "title": forms.TextInput(
15 attrs={
16 "class": "form-control",
17 "placeholder": "Enter an engaging post title",
18 "maxlength": "200",
19 }
20 ),
21 "url_slug": forms.TextInput(
22 attrs={
23 "class": "form-control",
24 "placeholder": "my-awesome-post",
25 "pattern": "[a-z0-9-]+",
26 "title": "Only lowercase letters, numbers, and hyphens allowed",
27 }
28 ),
29 "meta_description": forms.Textarea(
30 attrs={
31 "class": "form-control",
32 "placeholder": "Write a compelling meta description for SEO (max 160 characters)",
33 "rows": 3,
34 "maxlength": "160",
35 }
36 ),
37 "text": forms.Textarea(
38 attrs={
39 "class": "form-control rich-text-editor",
40 "id": "rich-editor",
41 "placeholder": "Start writing your amazing content here...",
42 }
43 ),
44 }
45 labels = {
46 "title": "Post Title",
47 "url_slug": "URL Slug",
48 "meta_description": "Meta Description (SEO)",
49 "text": "Content",
50 }
51 help_texts = {
52 "url_slug": "A unique URL-friendly identifier (use lowercase letters, numbers, and hyphens only)",
53 "meta_description": "This appears in search engine results. Keep it under 160 characters.",
54 "text": "Use the rich text editor to format your content with headings, images, videos, and tables.",
55 }
57 def clean_url_slug(self):
58 """Validate that the URL slug is unique and properly formatted"""
59 url_slug = self.cleaned_data.get("url_slug")
61 # Convert to lowercase and replace spaces with hyphens
62 url_slug = url_slug.lower().replace(" ", "-")
64 # Remove any characters that aren't letters, numbers, or hyphens
65 import re
67 url_slug = re.sub(r"[^a-z0-9-]", "", url_slug)
69 # Remove multiple consecutive hyphens
70 url_slug = re.sub(r"-+", "-", url_slug)
72 # Remove leading/trailing hyphens
73 url_slug = url_slug.strip("-")
75 if not url_slug:
76 raise forms.ValidationError("URL slug cannot be empty after formatting.")
78 # Check if the slug already exists (excluding the current instance if editing)
79 if self.instance.pk:
80 if (
81 Post.objects.filter(url_slug=url_slug)
82 .exclude(pk=self.instance.pk)
83 .exists()
84 ):
85 raise forms.ValidationError(
86 "This URL slug is already in use. Please choose a different one."
87 )
88 else:
89 if Post.objects.filter(url_slug=url_slug).exists():
90 raise forms.ValidationError(
91 "This URL slug is already in use. Please choose a different one."
92 )
94 return url_slug
96 def clean_meta_description(self):
97 """Validate meta description length"""
98 meta_description = self.cleaned_data.get("meta_description")
99 if meta_description and len(meta_description) > 160:
100 raise forms.ValidationError(
101 "Meta description must be 160 characters or less."
102 )
103 return meta_description
105 def clean_text(self):
106 text = self.cleaned_data.get("text")
107 # Sanitize rich text before saving
108 try:
109 return sanitize_html(text)
110 except Exception:
111 return text