Files
links/links/forms.py
T
2025-02-22 10:25:35 +11:00

130 lines
5.2 KiB
Python

from django import forms
from .models import Link, Page, Post, ImageCollection, Image, IPTVChannel, Tag
from simplemde.fields import SimpleMDEField
from django.utils.translation import gettext_lazy as _
from django.core.validators import URLValidator
import re
class LinkForm(forms.ModelForm):
text = SimpleMDEField()
class Meta:
model = Link
fields = ['alias', 'original_url', 'link_type', 'text', 'description', 'tags']
widgets = {
'link_type': forms.RadioSelect(),
'description': forms.Textarea(attrs={'rows': 3}),
'tags': forms.SelectMultiple(attrs={'class': 'select2'}),
}
def clean_original_url(self):
url = self.cleaned_data.get('original_url')
if not url:
return url
# Extract template parameters
template_params = re.findall(r'\{([^{}]*)\}', url)
# Temporarily replace template parameters with placeholder
temp_url = url
for param in template_params:
param_full = '{' + param + '}'
temp_url = temp_url.replace(param_full, 'template-param')
# Validate the URL with placeholders
try:
URLValidator()(temp_url)
except forms.ValidationError:
raise forms.ValidationError(_("Please enter a valid URL. Template parameters are allowed in the format {param_name,default=value}."))
return url
def clean(self):
cleaned_data = super().clean()
link_type = cleaned_data.get('link_type')
original_url = cleaned_data.get('original_url')
text = cleaned_data.get('text')
if link_type == Link.LinkType.LINK and not original_url:
raise forms.ValidationError(_("Original URL is required for Link type."))
elif link_type == Link.LinkType.CUSTOM and not text:
raise forms.ValidationError(_("Text is required for Custom type."))
return cleaned_data
class PageForm(forms.ModelForm):
class Meta:
model = Page
fields = ['url', 'title', 'summary', 'content', 'tags']
widgets = {
'summary': forms.Textarea(attrs={'rows': 3}),
'content': forms.Textarea(attrs={'rows': 10}),
'tags': forms.SelectMultiple(attrs={'class': 'select2'}),
}
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'summary', 'content', 'tags']
widgets = {
'summary': forms.Textarea(attrs={'rows': 3, 'class': 'mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}),
'content': forms.Textarea(attrs={'rows': 20}),
'tags': forms.SelectMultiple(attrs={'class': 'select2'}),
}
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [single_file_clean(d, initial) for d in data]
else:
result = single_file_clean(data, initial)
return result
class ImageCollectionForm(forms.ModelForm):
class Meta:
model = ImageCollection
fields = ['name', 'description', 'tags']
widgets = {
'description': forms.Textarea(attrs={'rows': 3}),
'tags': forms.SelectMultiple(attrs={'class': 'select2'}),
}
class ImageUploadForm(forms.ModelForm):
files = MultipleFileField(
widget=MultipleFileInput(attrs={
'accept': 'image/*',
'class': 'hidden',
})
)
class Meta:
model = Image
fields = ['title', 'description']
class TagForm(forms.ModelForm):
class Meta:
model = Tag
fields = ['name', 'description']
widgets = {
'name': forms.TextInput(attrs={'class': 'mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}),
'description': forms.Textarea(attrs={'rows': 3, 'class': 'mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}),
}
class IPTVChannelForm(forms.ModelForm):
class Meta:
model = IPTVChannel
fields = ['title', 'url', 'collection']
widgets = {
'title': forms.TextInput(attrs={'class': 'mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}),
'url': forms.URLInput(attrs={'class': 'mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}),
'collection': forms.Select(attrs={'class': 'mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}),
}