From f3516ffaf84c1a19daf06f422c4068431192c37b Mon Sep 17 00:00:00 2001 From: Dorian Lesbre <dorian.lesbre@gmail.com> Date: Sun, 7 Mar 2021 15:50:18 +0100 Subject: [PATCH] Functionnal activity choice --- home/forms.py | 20 +++++++++ home/static/css/style.css | 2 +- home/templates/inscription/form.html | 12 +++-- home/views.py | 65 +++++++++++++++++----------- 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/home/forms.py b/home/forms.py index a6cb16a..a0ba31c 100644 --- a/home/forms.py +++ b/home/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.core.exceptions import ValidationError from home.models import ActivityList, InterludesParticipant from shared.forms import FormRenderMixin @@ -30,3 +31,22 @@ class ActivityForm(FormRenderMixin, forms.ModelForm): class Meta: model = ActivityList fields = ("activity",) + +class BaseActivityFormSet(forms.BaseFormSet): + """Form set that fails if duplicate activities""" + def clean(self): + """Checks for duplicate activities""" + if any(self.errors): + # Don't bother validating the formset unless each form is valid on its own + return + activities = [] + for form in self.forms: + if self.can_delete and self._should_delete_form(form): + continue + activity = form.cleaned_data.get('activity') + if activity is None: + continue + if activity in activities: + print(activity) + raise ValidationError("Vous ne pouvez pas sélectionner une même activtté plusieurs fois") + activities.append(activity) diff --git a/home/static/css/style.css b/home/static/css/style.css index bef1b44..bd20b34 100644 --- a/home/static/css/style.css +++ b/home/static/css/style.css @@ -9,7 +9,6 @@ html, body { background-color: #dddddd; color: #333; - font-size: 18px; font-weight: 300; line-height: 1.5; font-family: Arial, Roboto, Helvetica, sans-serif; @@ -174,6 +173,7 @@ span.helptext { .button, .button:link, .button:visited, input[type=submit] { color: white; text-decoration: none; + font-size: 1em; background-color: var(--color_bg_1); padding: 7px 10px; margin: 5px; diff --git a/home/templates/inscription/form.html b/home/templates/inscription/form.html index a75b84b..7a0b252 100644 --- a/home/templates/inscription/form.html +++ b/home/templates/inscription/form.html @@ -3,10 +3,6 @@ {% block nav_inscription %}current{% endblock %} -{% block "head" %} - <!--<script src="{% static 'js/formset.js' %}"></script>--> -{% endblock %} - {% block "content" %} <h2>Inscriptions</h2> <form id="main_form" method="post" action="{% url 'inscription' %}"> @@ -14,6 +10,13 @@ {{ form.as_p }} <h3>Choix d'activités</h3> + + <p>Saissisez les activités auquelles vous voulez vous inscrire, par ordre de préférence.</p> + + {% if formset.non_form_errors %} + {{ formset.non_form_errors }} + {% endif %} + {{ formset.management_data }} {{ formset.management_form }} {% for form in formset %} @@ -50,6 +53,7 @@ function add_new_form(event) { new_form.innerHTML = new_form.innerHTML.replace(form_regex, `form-${form_count}-`); // add it and increment form total main_form.insertBefore(new_form, button_add_activity); + new_form.querySelector("select").value = ""; total_forms.setAttribute("value", `${form_count+1}`); } diff --git a/home/views.py b/home/views.py index b2f6b73..e127793 100644 --- a/home/views.py +++ b/home/views.py @@ -1,13 +1,13 @@ from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.sitemaps import Sitemap -from django.forms import modelformset_factory +from django.forms import formset_factory from django.shortcuts import redirect, render from django.urls import reverse from django.views.generic import UpdateView, TemplateView, View from home.models import ActivityList, InterludesActivity -from home.forms import ActivityForm, InscriptionForm +from home.forms import ActivityForm, BaseActivityFormSet, InscriptionForm from site_settings.models import SiteSettings @@ -41,35 +41,50 @@ class RegisterSignIn(TemplateView): l'utilisateur n'est pas connecté""" template_name = "inscription/signin.html" -class RegisterUpdateView(LoginRequiredMixin, UpdateView): +class RegisterUpdateView(LoginRequiredMixin, TemplateView): """Vue pour s'inscrire et modifier son inscription""" template_name = "inscription/form.html" form_class = InscriptionForm - formset = modelformset_factory(ActivityList, form=ActivityForm, extra=3) + formset_class = formset_factory(form=ActivityForm, extra=3, formset=BaseActivityFormSet) + + @staticmethod + def get_activities(participant): + activities = ActivityList.objects.filter(participant=participant).order_by("priority") + return [{"activity": act.activity} for act in activities] + + @staticmethod + def set_activities(participant, formset): + # delete old activites + ActivityList.objects.filter(participant=participant).delete() + + priority = 0 + for form in formset: + data = form.cleaned_data + if data: + activity = data["activity"] + ActivityList(priority=priority, participant=participant, activity=activity).save() + priority += 1 + + def get(self, request, *args, **kwargs): + participant = request.user.profile + activities = self.get_activities(participant) + form = self.form_class(instance=participant) + formset = self.formset_class(initial=activities) + context = {"form": form, "formset": formset} + return render(request, self.template_name, context) - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - context["formset"] = self.formset(queryset=ActivityList.objects.none()) - return context - - def get_object(self): - return self.request.user.profile - - def get_success_url(self): - return reverse("accounts:profile") + def post(self, request, *args, **kwargs): + form = self.form_class(request.POST, instance=request.user.profile) + formset = self.formset_class(request.POST) + if not (form.is_valid() and formset.is_valid()): + context = {"form": form, "formset": formset} + return render(request, self.template_name, context) - def form_valid(self, form): - messages.success(self.request, "Votre inscription a été enregistrée") - return super().form_valid(form) + form.save() + self.set_activities(request.user.profile, formset) - def post(self, request, *args, **kwargs): - form = self.form_class(request.POST) - formset = self.formset(request.POST) - if formset.is_valid(): - print("\n\n{} {}\n\n".format(len(formset), formset)) - else: - print("\n\nInvalid\n\n") - return super().post(request, *args, **kwargs) + messages.success(request, "Votre inscription a bien été enregistrée") + return redirect("accounts:profile", permanent=False) class RegisterView(View): """Vue pour l'inscription -- GitLab