forked from beba/foerderbarometer
Add ProjectRequestForm and ProjectRequestAdminForm with JSON-backed multi-selects and help texts
This commit is contained in:
parent
011e262df6
commit
4e6906e318
115
input/forms.py
115
input/forms.py
|
|
@ -5,6 +5,7 @@ from django.forms.renderers import DjangoTemplates
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from .models import ProjectRequest, PROJECT_CATEGORIES, WIKIMEDIA_CHOICES
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
TYPE_CHOICES,
|
TYPE_CHOICES,
|
||||||
|
|
@ -306,3 +307,117 @@ class ListForm(BaseApplicationForm, CommonOrderMixin):
|
||||||
model = List
|
model = List
|
||||||
fields = ['domain', 'address']
|
fields = ['domain', 'address']
|
||||||
exclude = ['intern_notes', 'survey_mail_send','mail_state']
|
exclude = ['intern_notes', 'survey_mail_send','mail_state']
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectRequestForm(CommonOrderMixin, forms.ModelForm):
|
||||||
|
"""
|
||||||
|
Public-facing form for < 1000 EUR project requests.
|
||||||
|
|
||||||
|
Key points:
|
||||||
|
- JSONField-backed multi-selects are exposed as MultipleChoiceField with checkbox widgets.
|
||||||
|
- We return `list(...)` in clean_* so the JSONField gets a native list.
|
||||||
|
- Extra UX tweaks: textareas for long text, number inputs with min/max/step, help_texts with links via format_html.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Expose JSON-backed categories as a checkbox multi-select
|
||||||
|
categories = forms.MultipleChoiceField(
|
||||||
|
choices=[(c, c) for c in PROJECT_CATEGORIES],
|
||||||
|
widget=forms.CheckboxSelectMultiple,
|
||||||
|
label='Projektkategorie',
|
||||||
|
help_text='In welche dieser Kategorien lässt sich dein Projekt einordnen?'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Expose JSON-backed wikimedia_projects as a checkbox multi-select
|
||||||
|
wikimedia_projects = forms.MultipleChoiceField(
|
||||||
|
choices=[(w, w) for w in WIKIMEDIA_CHOICES],
|
||||||
|
widget=forms.CheckboxSelectMultiple,
|
||||||
|
label='Wikimedia Projekt(e)',
|
||||||
|
help_text='Auf welches Wikimedia-Projekt bezieht sich dein Vorhaben?',
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ProjectRequest
|
||||||
|
fields = [
|
||||||
|
'realname', 'email',
|
||||||
|
'name', 'description',
|
||||||
|
'categories', 'categories_other',
|
||||||
|
'wikimedia_projects', 'wikimedia_other',
|
||||||
|
'start', 'end', 'participants_estimated',
|
||||||
|
'page', 'group', 'location',
|
||||||
|
'cost', 'insurance', 'notes',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Widgets are chosen for better UX and to gently guide valid inputs in the browser
|
||||||
|
widgets = {
|
||||||
|
'start': AdminDateWidget(),
|
||||||
|
'end': AdminDateWidget(),
|
||||||
|
|
||||||
|
# Long-text fields as textareas with sensible row counts
|
||||||
|
'description': forms.Textarea(attrs={'rows': 5}),
|
||||||
|
'notes': forms.Textarea(attrs={'rows': 6}),
|
||||||
|
|
||||||
|
# Integer-like fields: browser-side constraints (server still validates in the model)
|
||||||
|
'participants_estimated': forms.NumberInput(attrs={'min': 0, 'step': 1}),
|
||||||
|
'cost': forms.NumberInput(attrs={'min': 0, 'max': 1000, 'step': 1}),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Human-readable help_texts; use format_html for safe HTML (links)
|
||||||
|
help_texts = {
|
||||||
|
'name': 'Bitte gib einen Namen für das Projekt an.',
|
||||||
|
'description': 'Bitte beschreibe kurz, was die Ziele deines Projekts sind.',
|
||||||
|
'participants_estimated': 'Wie viele Personen werden ungefähr an diesem Projekt teilnehmen?',
|
||||||
|
'page': 'Bitte gib einen Link zur Projektseite in den Wikimedia-Projekten an, wenn vorhanden.',
|
||||||
|
'group': 'Sofern zutreffend: Bitte gib an, welche Personen das Projekt gemeinsam mit dir organisieren.',
|
||||||
|
'location': 'Sofern zutreffend: Bitte gib hier den Ort an, an welchem das Projekt stattfinden wird.',
|
||||||
|
'cost': 'Wie hoch werden die Projektkosten voraussichtlich sein? Bitte gib diese auf volle Euro gerundet an.',
|
||||||
|
'insurance': format_html(
|
||||||
|
'Möchtest du die <a href="https://de.wikipedia.org/wiki/Wikipedia:F%C3%B6rderung/Versicherung"> Unfall- und Haftpflichtversicherung</a> von Wikimedia Deutschland in Anspruch nehmen?'),
|
||||||
|
'notes': format_html(
|
||||||
|
'Falls du noch weitere Informationen hast, teile sie gern an dieser Stelle mit uns. Für umfangreichere Informationen, schreibe uns eine E-Mail an <a href="mailto:community@wikimedia.de">community@wikimedia.de</a>.'),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Persist multi-selects as Python lists so JSONField stores a JSON array
|
||||||
|
def clean_categories(self):
|
||||||
|
return list(self.cleaned_data.get('categories', []))
|
||||||
|
|
||||||
|
def clean_wikimedia_projects(self):
|
||||||
|
return list(self.cleaned_data.get('wikimedia_projects', []))
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectRequestAdminForm(forms.ModelForm):
|
||||||
|
"""
|
||||||
|
Admin form for ProjectRequest.
|
||||||
|
|
||||||
|
Key points:
|
||||||
|
- Same checkbox multi-selects for JSON-backed fields to improve admin UX.
|
||||||
|
- Keep fields="__all__" so admin users can inspect/set workflow fields if needed.
|
||||||
|
- Do NOT add extra business logic here; validation lives in the model's clean().
|
||||||
|
"""
|
||||||
|
|
||||||
|
categories = forms.MultipleChoiceField(
|
||||||
|
choices=[(c, c) for c in PROJECT_CATEGORIES],
|
||||||
|
widget=forms.CheckboxSelectMultiple,
|
||||||
|
label='Projektkategorie'
|
||||||
|
)
|
||||||
|
wikimedia_projects = forms.MultipleChoiceField(
|
||||||
|
choices=[(w, w) for w in WIKIMEDIA_CHOICES],
|
||||||
|
widget=forms.CheckboxSelectMultiple,
|
||||||
|
label='Wikimedia Projekt(e)'
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ProjectRequest
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
# Make longer texts easier to edit in the admin UI
|
||||||
|
widgets = {
|
||||||
|
'description': forms.Textarea(attrs={'rows': 5}),
|
||||||
|
'notes': forms.Textarea(attrs={'rows': 6}),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure JSONField receives a list
|
||||||
|
def clean_categories(self):
|
||||||
|
return list(self.cleaned_data.get('categories', []))
|
||||||
|
|
||||||
|
def clean_wikimedia_projects(self):
|
||||||
|
return list(self.cleaned_data.get('wikimedia_projects', []))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue