Verified Commit d5ad2c51 authored by Sli's avatar Sli

clubs: Handle bulk add of users in clubs and refresh of the form handling

parent e8ee9122
Pipeline #1720 failed with stage
in 12 minutes and 7 seconds
......@@ -11,7 +11,7 @@
<td>{% trans %}Since{% endtrans %}</td>
{% for m in club.members.filter(end_date=None).order_by('-role').all() %}
{% for m in members %}
<td>{{ user_profile_link(m.user) }}</td>
<td>{{ settings.SITH_CLUB_ROLES[m.role] }}</td>
......@@ -30,6 +30,3 @@
<p><input type="submit" value="{% trans %}Add{% endtrans %}" /></p>
{% endblock %}
......@@ -33,7 +33,7 @@ from django.core.urlresolvers import reverse, reverse_lazy
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext as _t
from ajax_select.fields import AutoCompleteSelectField
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect
......@@ -44,6 +44,7 @@ from core.views import (
from core.views.forms import SelectDate, SelectDateTime
from club.models import Club, Membership, Mailing, MailingSubscription
......@@ -305,7 +306,7 @@ class ClubToolsView(ClubTabsMixin, CanEditMixin, DetailView):
current_tab = "tools"
class ClubMemberForm(forms.ModelForm):
class ClubMemberForm(forms.Form):
Form handling the members of a club
......@@ -313,24 +314,68 @@ class ClubMemberForm(forms.ModelForm):
error_css_class = "error"
required_css_class = "required"
class Meta:
model = Membership
fields = ["user", "role", "start_date", "description"]
widgets = {"start_date": SelectDate}
user = AutoCompleteSelectField(
"users", required=True, label=_("Select user"), help_text=None
users = AutoCompleteSelectMultipleField(
label=_("Users to add"),
help_text=_("Search users to add (one or more)."),
def save(self, *args, **kwargs):
def __init__(self, *args, **kwargs): = kwargs.pop("club")
self.request_user = kwargs.pop("request_user")
super(ClubMemberForm, self).__init__(*args, **kwargs)
# Using a ModelForm forces a save and we don't want that
# We want the view to process the model creation since they are multiple users
fields=("role", "start_date", "description"),
widgets={"start_date": SelectDate},
if not self.request_user.is_root:
def clean_users(self):
Overloaded to return the club, and not to a Membership object that has no view
Check that the user is not trying to add an user already in the club
cleaned_data = super(ClubMemberForm, self).clean()
users = []
for user_id in cleaned_data["users"]:
user = User.objects.filter(id=user_id).first()
if not user:
raise forms.ValidationError(
_("One of the selected users doesn't exist", code="invalid")
raise forms.ValidationError(
_("You can not add the same user twice"), code="invalid"
return users
def clean(self):
Check user rights
super(ClubMemberForm, self).save(*args, **kwargs)
cleaned_data = super(ClubMemberForm, self).clean()
request_user = self.request_user
membership =
if not (
cleaned_data["role"] <= SITH_MAXIMUM_FREE_ROLE
or (membership is not None and membership.role >= cleaned_data["role"])
or request_user.is_board_member
or request_user.is_root
raise forms.ValidationError(_("You do not have the permission to do that"))
return cleaned_data
class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView):
class ClubMembersView(ClubTabsMixin, CanViewMixin, DetailFormView):
View of a club's members
......@@ -341,52 +386,39 @@ class ClubMembersView(ClubTabsMixin, CanViewMixin, UpdateView):
template_name = "club/club_members.jinja"
current_tab = "members"
def get_form(self):
Here we get a Membership object, but the view handles Club object.
That's why the save method of ClubMemberForm is overridden.
form = super(ClubMembersView, self).get_form()
if (
"user" in and"user") != ""
): # Load an existing membership if possible
form.instance = (
if form.instance is None: # Instanciate a new membership
form.instance = Membership(club=self.object, user=self.request.user)
if not self.request.user.is_root:
form.fields.pop("start_date", None)
return form
def get_form_kwargs(self):
kwargs = super(ClubMembersView, self).get_form_kwargs()
kwargs["request_user"] = self.request_user
kwargs["club"] = self.get_object()
return kwargs
def get_context_data(self, *args, **kwargs):
kwargs = super(ClubMembersView, self).get_context_data(*args, **kwargs)
kwargs["members"] = (
return kwargs
def form_valid(self, form):
Check user rights
user = self.request.user
ms = self.object.get_membership_for(user)
if (
form.cleaned_data["role"] <= SITH_MAXIMUM_FREE_ROLE
or (ms is not None and ms.role >= form.cleaned_data["role"])
or user.is_board_member
or user.is_root
form = self.form_class()
return super(ModelFormMixin, self).form_valid(form)
form.add_error(None, _("You do not have the permission to do that"))
return self.form_invalid(form)
resp = super(ClubMembersView, self).form_valid(form)
data = form.clean()
users = data.pop("users", [])
for user in users:
Membership(club=self.get_object(), user=user, **data).save()
return resp
def dispatch(self, request, *args, **kwargs):
self.request = request
self.request_user = request.user
return super(ClubMembersView, self).dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy("club:club_members", kwargs={"club_id":})
return reverse_lazy(
"club:club_members", kwargs={"club_id": self.get_object().id}
class ClubOldMembersView(ClubTabsMixin, CanViewMixin, DetailView):
......@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-22 14:57+0200\n"
"POT-Creation-Date: 2019-04-24 03:06+0200\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Skia <>\n"
"Language-Team: AE info <>\n"
......@@ -177,7 +177,7 @@ msgstr "type de cible"
#: accounting/ club/
#: club/templates/club/club_members.jinja:8
#: club/templates/club/club_old_members.jinja:8
#: club/templates/club/mailing.jinja:28 club/
#: club/templates/club/mailing.jinja:28 club/
#: counter/templates/counter/cash_summary_list.jinja:32
#: counter/templates/counter/stats.jinja:15
#: counter/templates/counter/stats.jinja:52
......@@ -386,7 +386,7 @@ msgid "Delete"
msgstr "Supprimer"
#: accounting/templates/accounting/bank_account_details.jinja:18
#: club/ core/views/ sas/templates/sas/picture.jinja:86
#: club/ core/views/ sas/templates/sas/picture.jinja:86
msgid "Infos"
msgstr "Infos"
......@@ -405,7 +405,7 @@ msgstr "Nouveau compte club"
#: accounting/templates/accounting/bank_account_details.jinja:27
#: accounting/templates/accounting/bank_account_list.jinja:22
#: accounting/templates/accounting/club_account_details.jinja:58
#: accounting/templates/accounting/journal_details.jinja:89 club/
#: accounting/templates/accounting/journal_details.jinja:89 club/
#: com/templates/com/news_admin_list.jinja:39
#: com/templates/com/news_admin_list.jinja:68
#: com/templates/com/news_admin_list.jinja:115
......@@ -1070,8 +1070,8 @@ msgstr "Du"
msgid "To"
msgstr "Au"
#: club/templates/club/club_sellings.jinja:5 club/
#: club/ counter/templates/counter/counter_main.jinja:19
#: club/templates/club/club_sellings.jinja:5 club/
#: club/ counter/templates/counter/counter_main.jinja:19
#: counter/templates/counter/last_ops.jinja:35
msgid "Sellings"
msgstr "Ventes"
......@@ -1097,7 +1097,7 @@ msgstr "unités"
msgid "Benefit: "
msgstr "Bénéfice : "
#: club/templates/club/club_sellings.jinja:21 club/
#: club/templates/club/club_sellings.jinja:21 club/
#: core/templates/core/user_account_detail.jinja:18
#: core/templates/core/user_account_detail.jinja:51
#: counter/templates/counter/cash_summary_list.jinja:33 counter/
......@@ -1246,60 +1246,71 @@ msgstr "Aucune page n'existe pour ce club"
msgid "Club stats"
msgstr "Statistiques du club"
#: club/
#: club/
msgid "Members"
msgstr "Membres"
#: club/
#: club/
msgid "Old members"
msgstr "Anciens membres"
#: club/ core/templates/core/page.jinja:33
#: club/ core/templates/core/page.jinja:33
msgid "History"
msgstr "Historique"
#: club/ core/templates/core/base.jinja:121 core/views/
#: club/ core/templates/core/base.jinja:121 core/views/
#: sas/templates/sas/picture.jinja:95 trombi/
msgid "Tools"
msgstr "Outils"
#: club/
#: club/
msgid "Edit club page"
msgstr "Éditer la page de club"
#: club/
#: club/
msgid "Mailing list"
msgstr "Listes de diffusion"
#: club/ com/
#: club/ com/
msgid "Posters list"
msgstr "Liste d'affiches"
#: club/ counter/templates/counter/counter_list.jinja:21
#: club/ counter/templates/counter/counter_list.jinja:21
#: counter/templates/counter/counter_list.jinja:43
#: counter/templates/counter/counter_list.jinja:59
msgid "Props"
msgstr "Propriétés"
#: club/ core/views/ counter/
#: trombi/
msgid "Select user"
msgstr "Choisir un utilisateur"
#: club/
msgid "Users to add"
msgstr "Utilisateurs à ajouter"
#: club/ core/views/
msgid "Search users to add (one or more)."
msgstr "Recherche les utilisateurs à ajouter (un ou plus)."
#: club/
msgid "One of the selected users doesn't exist"
msgstr "Un des utilisateurs sélectionné n'existe pas"
#: club/ core/views/
msgid "You can not add the same user twice"
msgstr "Vous ne pouvez pas ajouter deux fois le même utilisateur"
#: club/ sas/ sas/ sas/
#: club/ sas/ sas/ sas/
msgid "You do not have the permission to do that"
msgstr "Vous n'avez pas la permission de faire cela"
#: club/ counter/
#: club/ counter/
msgid "Begin date"
msgstr "Date de début"
#: club/ com/ com/ counter/
#: club/ com/ com/ counter/
#: election/ subscription/
msgid "End date"
msgstr "Date de fin"
#: club/ core/templates/core/user_stats.jinja:27
#: club/ core/templates/core/user_stats.jinja:27
#: counter/
msgid "Product"
msgstr "Produit"
......@@ -3507,6 +3518,10 @@ msgstr "Parrain"
msgid "Godchild"
msgstr "Fillot"
#: core/views/ counter/ trombi/
msgid "Select user"
msgstr "Choisir un utilisateur"
#: core/views/ core/views/ election/
#: election/
msgid "edit groups"
......@@ -3525,14 +3540,6 @@ msgstr "Utilisateurs à retirer du groupe"
msgid "Users to add to group"
msgstr "Utilisateurs à ajouter au groupe"
#: core/views/
msgid "Search users to add (one or more)."
msgstr "Recherche les utilisateurs à ajouter (un ou plus)."
#: core/views/
msgid "You can not add the same user twice"
msgstr "Vous ne pouvez pas ajouter deux fois le même utilisateur"
#: core/views/ trombi/templates/trombi/export.jinja:25
#: trombi/templates/trombi/user_profile.jinja:11
msgid "Pictures"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment