from smtplib import SMTPException from django.shortcuts import render from django.http import HttpResponse from django.utils.safestring import mark_safe from formtools.wizard.views import CookieWizardView from django.core.mail import BadHeaderError, EmailMultiAlternatives from django.template.loader import get_template from django.conf import settings from django.contrib.auth.decorators import login_required from django.views.generic.edit import FormView from .forms import ( ExternForm, LibraryForm, ELiteratureForm, SoftwareForm, IFGForm, LiteratureForm, TravelForm, EmailForm, ListForm, BusinessCardForm, ) from .models import TYPE_CHOICES, MODELS, TYPE_BIB, TYPE_ELIT, TYPE_SOFT LIBRARY_FORMS = { TYPE_BIB: LibraryForm, TYPE_ELIT: ELiteratureForm, TYPE_SOFT: SoftwareForm, } HELP_TEXTS = { "IFG": { "notes": ( "Bitte gib an, wie die gewonnenen Informationen den
" "Wikimedia-Projekten zugute kommen sollen." ) }, "MAIL": { "domain": ( "Mit welcher Domain, bzw. für welches Wikimedia-Projekt,
" "möchtest du eine Mailadresse beantragen?" ) }, "LIT": { "notes": "Bitte gib an, wofür du die Literatur verwenden möchtest." }, "LIST": { "domain": ( "Mit welcher Domain, bzw. für welches Wikimedia-Projekt,
" "möchtest du eine Mailingliste beantragen?" ) }, } def auth_deny(choice, pk, auth): if choice not in MODELS: return HttpResponse(f'ERROR! UNKNOWN CHOICE TYPE! {choice}') MODELS[choice].set_granted(pk, auth) @login_required def export(request): '''export the project database to a csv''' return HttpResponse('WE WANT CSV!') @login_required def authorize(request, choice, pk): '''If IF grant a support they click a link in a mail which leads here. We write the granted field in the database here and set a timestamp.''' if ret := auth_deny(choice, pk, True): return ret else: return HttpResponse(f"AUTHORIZED! choice: {choice}, pk: {pk}") @login_required def deny(request, choice, pk): '''If IF denies a support they click a link in a mail which leads here We write the granted field in the database here.''' if ret := auth_deny(choice, pk, False): return ret else: return HttpResponse(f"DENIED! choice: {choice}, pk: {pk}") def done(request): return HttpResponse( "Deine Anfrage wurde gesendet. Du erhältst in Kürze eine E-Mail-Benachrichtigung mit deinen Angaben. Für alle Fragen kontaktiere bitte das Team Communitys und Engagement unter community@wikimedia.de.") def index(request): return render(request, 'input/index.html') class BaseApplicationView(FormView): """ Base view for all application types. - Each application type (travel, literature, email, etc.) gets its own subclass. - Renders the generic form template. - Handles saving the submitted form to the database. - Adds extra fields from the session or request type if needed. - Applies optional help_text overrides for certain fields. - Sends confirmation mail to the applicant. - Sends notification mail to the internal IF address. - Returns the "done" response after successful processing. """ template_name = "input/forms/form_generic.html" type_code: str = "" def get_context_data(self, **kwargs): """Add the human-readable type string (from TYPE_CHOICES) to the template context.""" ctx = super().get_context_data(**kwargs) ctx["typestring"] = TYPE_CHOICES.get(self.type_code, self.type_code) return ctx def get_form(self, form_class=None): """Return the form instance and inject custom help_texts if defined for this type.""" form = super().get_form(form_class) # Apply help_text overrides if defined for this type_code if self.type_code in HELP_TEXTS: for field, text in HELP_TEXTS[self.type_code].items(): if field in form.fields: form.fields[field].help_text = mark_safe(text) return form def form_valid(self, form): """ Process a valid form submission: - Enrich form data (e.g., set type_code, handle special rules). - Save the model instance and related data. - Send confirmation and notification mails. - Return the "done" response. """ # Collect cleaned data and mark the current type data = form.cleaned_data.copy() data["choice"] = self.type_code # Special rule for literature applications if self.type_code == "LIT" and data.get("selfbuy") == "TRUE": data["selfbuy_give_data"] = "False" # Save model instance modell = form.save(commit=False) # Username from session if present user = self.request.session.get("user") if user: modell.username = user.get("username") # Copy common fields if provided by the form if "realname" in data: modell.realname = data["realname"] if "email" in data: modell.email = data["email"] # Set model.type for specific request types if self.type_code in ("BIB", "ELIT", "SOFT"): modell.type = self.type_code # Literature-specific extra field if self.type_code == "LIT" and "selfbuy_give_data" in data: modell.selfbuy_give_data = data["selfbuy_give_data"] modell.save() if hasattr(form, "save_m2m"): form.save_m2m() # Prepare minimal mail context and send mails data["pk"] = modell.pk data["url_prefix"] = settings.EMAIL_URL_PREFIX data["typestring"] = TYPE_CHOICES.get(self.type_code, self.type_code) context = {"data": data} try: # Mail to applicant txt1 = get_template("input/ifg_volunteer_mail.txt").render(context) html1 = get_template("input/ifg_volunteer_mail.html").render(context) msg1 = EmailMultiAlternatives( "Formular ausgefüllt", txt1, settings.IF_EMAIL, [data["email"]] ) msg1.attach_alternative(html1, "text/html") msg1.send() # Mail to IF txt2 = get_template("input/if_mail.txt").render(context) html2 = get_template("input/if_mail.html").render(context) msg2 = EmailMultiAlternatives( "Formular ausgefüllt", txt2, settings.IF_EMAIL, [settings.IF_EMAIL] ) msg2.attach_alternative(html2, "text/html") msg2.send() except BadHeaderError: modell.delete() return HttpResponse("Invalid header found. Data not saved!") except SMTPException: modell.delete() return HttpResponse("Error in sending mails (probably wrong adress?). Data not saved!") return done(self.request) class TravelApplicationView(BaseApplicationView): form_class = TravelForm type_code = "TRAV" class LibraryApplicationView(BaseApplicationView): form_class = LibraryForm type_code = "BIB" class ELiteratureApplicationView(BaseApplicationView): form_class = ELiteratureForm type_code = "ELIT" class SoftwareApplicationView(BaseApplicationView): form_class = SoftwareForm type_code = "SOFT" class IFGApplicationView(BaseApplicationView): form_class = IFGForm type_code = "IFG" class EmailApplicationView(BaseApplicationView): form_class = EmailForm type_code = "MAIL" class LiteratureApplicationView(BaseApplicationView): form_class = LiteratureForm type_code = "LIT" class ListApplicationView(BaseApplicationView): form_class = ListForm type_code = "LIST" class BusinessCardApplicationView(BaseApplicationView): form_class = BusinessCardForm type_code = "VIS"