diff --git a/bds/mixins.py b/bds/mixins.py index 16399704..30334e9f 100644 --- a/bds/mixins.py +++ b/bds/mixins.py @@ -1,5 +1,103 @@ from django.contrib.auth.mixins import PermissionRequiredMixin +from django.core.exceptions import ImproperlyConfigured +from django.http import HttpResponseRedirect +from django.views.generic.base import ContextMixin, TemplateResponseMixin, View class StaffRequiredMixin(PermissionRequiredMixin): permission_required = "bds.is_team" + + +class MultipleFormMixin(ContextMixin): + """ Mixin pour gérer plusieurs formulaires dans la même vue. + Le fonctionnement est relativement identique à celui de + FormMixin. + """ + + form_classes = {} + prefixes = {} + initial = {} + + success_url = None + + def get_form_classes(self): + return self.form_classes + + def get_initial(self, form_name): + initial_attr = "%s_initial" % form_name + + initial_method = "get_%s_initial" % form_name + initial_method = getattr(self, initial_method, None) + + if hasattr(self, initial_attr): + return getattr(self, initial_attr) + elif callable(initial_method): + return initial_method() + else: + return self.initial.copy() + + def get_prefix(self, form_name): + return self.prefixes.get(form_name, form_name) + + def get_instance(self, form_name): + # Au cas où certaines des forms soient des ModelForms + instance_method = "get_%s_instance" % form_name + instance_method = getattr(self, instance_method, None) + + if callable(instance_method): + return instance_method() + else: + return None + + def get_form_kwargs(self, form_name): + kwargs = { + "initial": self.get_initial(form_name), + "prefix": self.get_prefix(form_name), + "instance": self.get_instance(form_name), + } + + if self.request.method in ("POST", "PUT"): + kwargs.update({"data": self.request.POST, "files": self.request.FILES}) + + return kwargs + + def get_forms(self): + form_classes = self.get_form_classes() + return { + form_name: form_class(**self.get_form_kwargs(form_name)) + for form_name, form_class in form_classes.items() + } + + def get_success_url(self): + if not self.success_url: + raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.") + return str(self.success_url) + + def form_valid(self, forms): + # on garde le nom form_valid pour l'interface avec SuccessMessageMixin + return HttpResponseRedirect(self.get_success_url()) + + def form_invalid(self, forms): + """If the form is invalid, render the invalid form.""" + return self.render_to_response(self.get_context_data(forms=forms)) + + +class ProcessMultipleFormView(View): + def get(self, request, *args, **kwargs): + forms = self.get_forms() + return self.render_to_response(self.get_context_data(forms=forms)) + + def post(self, request, *args, **kwargs): + forms = self.get_forms() + if all(form.is_valid() for form in forms.values()): + return self.form_valid(forms) + else: + return self.form_invalid(forms) + + +class BaseMultipleFormView(MultipleFormMixin, ProcessMultipleFormView): + pass + + +class MultipleFormView(TemplateResponseMixin, BaseMultipleFormView): + pass