diff --git a/froide_govplan/admin.py b/froide_govplan/admin.py index adbfcf8..20e055b 100644 --- a/froide_govplan/admin.py +++ b/froide_govplan/admin.py @@ -1,13 +1,12 @@ -from django import forms from django.contrib import admin, auth from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from adminsortable2.admin import SortableAdminMixin -from tinymce.widgets import TinyMCE from froide.helper.widgets import TagAutocompleteWidget +from .forms import GovernmentPlanForm, GovernmentPlanUpdateForm from .models import ( Government, GovernmentPlan, @@ -22,7 +21,7 @@ class GovPlanAdminSite(admin.AdminSite): site_header = "Regierungsvorhaben" -class GovernmentPlanAdminForm(forms.ModelForm): +class GovernmentPlanAdminForm(GovernmentPlanForm): class Meta: model = GovernmentPlan fields = "__all__" @@ -33,13 +32,6 @@ class GovernmentPlanAdminForm(forms.ModelForm): } -class GovernmentPlanUpdateAdminForm(forms.ModelForm): - class Meta: - model = GovernmentPlanUpdate - fields = "__all__" - widgets = {"content": TinyMCE(attrs={"cols": 80, "rows": 30})} - - class GovernmentAdmin(admin.ModelAdmin): prepopulated_fields = {"slug": ("name",)} list_display = ("name", "public", "start_date", "end_date") @@ -58,7 +50,7 @@ def get_allowed_plans(request): class GovernmentPlanAdmin(admin.ModelAdmin): - form = GovernmentPlanAdminForm + form = GovernmentPlanForm save_on_top = True prepopulated_fields = {"slug": ("title",)} @@ -122,7 +114,7 @@ class GovernmentPlanAdmin(admin.ModelAdmin): class GovernmentPlanUpdateAdmin(admin.ModelAdmin): - form = GovernmentPlanUpdateAdminForm + form = GovernmentPlanUpdateForm save_on_top = True raw_id_fields = ("user", "foirequest") date_hierarchy = "timestamp" diff --git a/froide_govplan/forms.py b/froide_govplan/forms.py new file mode 100644 index 0000000..7430a49 --- /dev/null +++ b/froide_govplan/forms.py @@ -0,0 +1,62 @@ +from django import forms +from django.utils.safestring import mark_safe + +import bleach +from bleach.linkifier import Linker +from tinymce.widgets import TinyMCE + +from .models import GovernmentPlan, GovernmentPlanUpdate + +BLEACH_OPTIONS = { + "tags": [ + "a", + "strong", + "b", + "i", + "em", + "ul", + "ol", + "li", + "p", + "h3", + "h4", + "h5", + "blockquote", + ] +} + + +def set_link_attrs(attrs, new=False): + attrs[(None, "rel")] = "noopener" + return attrs + + +class BleachField(forms.CharField): + """Bleach form field""" + + def to_python(self, value): + """ + Strips any dodgy HTML tags from the input. + Mark the return value as template safe. + """ + if value in self.empty_values: + return self.empty_value + cleaned = bleach.clean(value, **BLEACH_OPTIONS) + linker = Linker(callbacks=[set_link_attrs]) + return mark_safe(linker.linkify(cleaned)) + + +class GovernmentPlanForm(forms.ModelForm): + description = BleachField(widget=TinyMCE(attrs={"cols": 80, "rows": 30})) + + class Meta: + model = GovernmentPlan + fields = "__all__" + + +class GovernmentPlanUpdateForm(forms.ModelForm): + content = BleachField(widget=TinyMCE(attrs={"cols": 80, "rows": 30})) + + class Meta: + model = GovernmentPlanUpdate + fields = "__all__"