from django import forms from django.contrib.auth import get_user_model from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Field from markdownfield.widgets import MDEWidget from .widgets import ImagePreviewWidget from .models import Post, PostCategory from mptt.forms import TreeNodeChoiceField User = get_user_model() class PostCategoryForm(forms.ModelForm): class Meta: model = PostCategory fields = ["name", "slug", "parent", "description"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_tag = False self.helper.layout = Layout( Field("name"), Field("slug"), Field("parent"), Field("description"), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Use TreeNodeChoiceField for hierarchical parent selection self.fields["parent"] = TreeNodeChoiceField( queryset=PostCategory.objects.all(), required=False, level_indicator="— " ) class PostForm(forms.ModelForm): tags = forms.CharField(label="Tags", required=False, help_text="Comma-separated") class Meta: model = Post fields = [ "title", "slug", "category", "author", "excerpt", "feature_image", "content", "status", "published_at", ] widgets = { "published_at": forms.DateTimeInput(attrs={"type": "datetime-local"}), "content": MDEWidget(attrs={"rows": 20}), "feature_image": ImagePreviewWidget(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper = FormHelper() self.helper.form_tag = False self.helper.layout = Layout( Field("title"), Field("slug"), Field("category"), Field("author"), Field("excerpt"), Field("feature_image"), Field("content"), Field("status"), Field("published_at"), Field("tags"), ) # Initialize tags from instance if self.instance and getattr(self.instance, "pk", None): try: names = list(self.instance.tags.names()) self.fields["tags"].initial = ", ".join(names) except Exception: self.fields["tags"].initial = "" def save(self, commit=True): obj = super().save(commit) tags = [t.strip() for t in self.cleaned_data.get("tags", "").split(",") if t.strip()] try: if commit: obj.tags.set(tags) except Exception: pass return obj