From 82582866b4ad129c7d006e8682bac588d1e01ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sun, 15 Oct 2017 23:46:54 +0200 Subject: [PATCH] =?UTF-8?q?Clean=20forms/views/urls=20related=20to=20kfeta?= =?UTF-8?q?uth.Group=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …and it becomes possible to add extra forms/formsets to the create and update group views. --- kfet/auth/forms.py | 3 +- kfet/auth/templates/kfet/group_form.html | 58 +++++++++ kfet/auth/templates/kfet/group_list.html | 58 +++++++++ kfet/auth/urls.py | 18 +++ kfet/auth/views.py | 116 ++++++++++++++---- kfet/forms.py | 2 - kfet/models.py | 5 + kfet/static/kfet/css/base/forms.css | 52 ++++++++ kfet/static/kfet/css/index.css | 13 +- kfet/templates/kfet/account.html | 3 +- kfet/templates/kfet/account_group.html | 61 --------- kfet/templates/kfet/account_group_form.html | 10 -- .../kfet/form_field_base_snippet.html | 19 +++ kfet/templates/kfet/form_field_snippet.html | 30 +++-- kfet/templates/kfet/form_full_snippet.html | 2 +- kfet/templates/kfet/form_snippet.html | 8 +- kfet/templates/kfet/form_submit_snippet.html | 12 +- kfet/tests/test_models.py | 10 ++ kfet/urls.py | 19 +-- kfet/views.py | 8 +- 20 files changed, 353 insertions(+), 154 deletions(-) create mode 100644 kfet/auth/templates/kfet/group_form.html create mode 100644 kfet/auth/templates/kfet/group_list.html create mode 100644 kfet/auth/urls.py create mode 100644 kfet/static/kfet/css/base/forms.css delete mode 100644 kfet/templates/kfet/account_group.html delete mode 100644 kfet/templates/kfet/account_group_form.html create mode 100644 kfet/templates/kfet/form_field_base_snippet.html diff --git a/kfet/auth/forms.py b/kfet/auth/forms.py index 0de47664..5ca5da70 100644 --- a/kfet/auth/forms.py +++ b/kfet/auth/forms.py @@ -4,13 +4,12 @@ from django.utils.translation import ugettext_lazy as _ from utils.forms import KeepUnselectableModelFormMixin - from .fields import GroupsField, CorePermissionsField from .models import Group class GroupForm(KeepUnselectableModelFormMixin, forms.ModelForm): - permissions = CorePermissionsField(label=_("Permissions"), required=False) + permissions = CorePermissionsField(label='', required=False) keep_unselectable_fields = ['permissions'] diff --git a/kfet/auth/templates/kfet/group_form.html b/kfet/auth/templates/kfet/group_form.html new file mode 100644 index 00000000..44ecfb38 --- /dev/null +++ b/kfet/auth/templates/kfet/group_form.html @@ -0,0 +1,58 @@ +{% extends "kfet/base_form.html" %} +{% load i18n %} + +{% block title %} + {% if not form.instance.pk %} + {% trans "Création d'un groupe" %} + {% else %} + {% blocktrans with name=form.instance.name %} + Modification du groupe "{{ name }}" + {% endblocktrans %} + {% endif %} +{% endblock %} + +{% block header-title %} + {% if not form.instance.pk %} + {% trans "Création d'un groupe" %} + {% else %} + {% blocktrans with name=form.instance.name %} + {{ name }} + Modification du groupe + {% endblocktrans %} + {% endif %} +{% endblock %} + +{% block main %} + +
+ {% csrf_token %} + + {# Base form #} +
+ {% include "kfet/form_snippet.html" with form=form %} +
+ + {# Extra forms #} + {% for extra in extras %} +

+ {{ extra.title }}
+ {{ extra.description }} +

+ + {% for extra_form in extra.forms %} +
+ {% with as_panel=extra_form.as_admin_panel %} + {% if as_panel %} + {{ as_panel }} + {% else %} + {% include "kfet/form_snippet.html" with form=extra_form %} + {% endif %} + {% endwith %} +
+ {% endfor %} + {% endfor %} + + {% include "kfet/form_submit_snippet.html" %} +
+ +{% endblock %} diff --git a/kfet/auth/templates/kfet/group_list.html b/kfet/auth/templates/kfet/group_list.html new file mode 100644 index 00000000..768fa30d --- /dev/null +++ b/kfet/auth/templates/kfet/group_list.html @@ -0,0 +1,58 @@ +{% extends "kfet/base_col_2.html" %} +{% load i18n %} + +{% block title %}{% trans "Groupes de comptes" %}{% endblock %} +{% block header-title %}{% trans "Groupes de comptes" %}{% endblock %} + +{% block fixed %} + +
+ + {% trans "Créer un groupe" %} + +
+ +{% endblock %} + +{% block main %} + +{% for group in groups %} +
+
+ {{ group.name }} + +
+
+

Comptes

+ {% with users=group.user_set.all %} + {% if users %} +
+
    + {% for user in group.user_set.all %} + {% with kfet_user=user.profile.account_kfet %} +
  • + {{ kfet_user }} +
  • + {% endwith %} + {% endfor %} +
+ {% else %} +
+

+ {% blocktrans %} + Aucun compte n'est associé à ce groupe. Rendez-vous sur la page + d'édition d'un compte pour l'y ajouter. + {% endblocktrans %} +

+
+ {% endif %} + {% endwith %} +
+
+{% endfor %} + +{% endblock %} diff --git a/kfet/auth/urls.py b/kfet/auth/urls.py new file mode 100644 index 00000000..5937663e --- /dev/null +++ b/kfet/auth/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls import include, url + +from . import views + +group_patterns = [ + url(r'^$', views.group_index, + name='kfet.group'), + url(r'^nouveau/$', views.group_create, + name='kfet.group.create'), + url('^(?P\d+)/edition/$', views.group_update, + name='kfet.group.update'), +] + +urlpatterns = [ + url(r'^groupes/', include(group_patterns)), + url(r'^login/generic', views.login_generic, + name='kfet.login.generic'), +] diff --git a/kfet/auth/views.py b/kfet/auth/views.py index 7d7b48c5..018e33db 100644 --- a/kfet/auth/views.py +++ b/kfet/auth/views.py @@ -1,22 +1,21 @@ from django.contrib import messages -from django.contrib.messages.views import SuccessMessageMixin -from django.contrib.auth import authenticate, login +from django.contrib.auth import authenticate, get_user_model, login from django.contrib.auth.decorators import permission_required -from django.contrib.auth.models import User from django.contrib.auth.views import redirect_to_login -from django.core.urlresolvers import reverse, reverse_lazy +from django.core.urlresolvers import reverse from django.db.models import Prefetch from django.http import QueryDict -from django.shortcuts import redirect, render +from django.shortcuts import get_object_or_404, redirect, render from django.utils.decorators import method_decorator from django.utils.translation import ugettext_lazy as _ from django.views.generic import View from django.views.decorators.http import require_http_methods -from django.views.generic.edit import CreateView, UpdateView from .forms import GroupForm from .models import GenericTeamToken, Group +User = get_user_model() + class GenericLoginView(View): """ @@ -105,37 +104,102 @@ login_generic = GenericLoginView.as_view() @permission_required('kfetauth.view_group') -def account_group(request): +def group_index(request): user_pre = Prefetch( 'user_set', queryset=User.objects.select_related('profile__account_kfet'), ) - groups = ( - Group.objects - .prefetch_related('permissions', user_pre) - ) - return render(request, 'kfet/account_group.html', { + groups = Group.objects.prefetch_related(user_pre) + return render(request, 'kfet/group_list.html', { 'groups': groups, }) -class BaseAccountGroupFormViewMixin: - model = Group - form_class = GroupForm - template_name = 'kfet/account_group_form.html' - success_url = reverse_lazy('kfet.account.group') +_group_formview_extras = None -class AccountGroupFormViewMixin( - SuccessMessageMixin, - BaseAccountGroupFormViewMixin, -): - pass +def get_group_formview_extras(): + global _group_formview_extras + + if _group_formview_extras is None: + _group_formview_extras = [] + + # Register additional group forms below. + + return [extra.copy() for extra in _group_formview_extras] -class AccountGroupCreate(AccountGroupFormViewMixin, CreateView): - success_message = 'Nouveau groupe : %(name)s' +@permission_required('kfetauth.add_group') +def group_create(request): + group = Group() + + extras = get_group_formview_extras() + + if request.method == 'POST': + form = GroupForm(request.POST, instance=group) + for extra in extras: + extra['forms'] = [ + form_cls( + request.POST, request.FILES, instance=group, **form_kwargs) + for form_cls, form_kwargs in extra['form_classes'] + ] + extra_forms = sum((extra['forms'] for extra in extras), []) + + if form.is_valid() and all(form.is_valid() for form in extra_forms): + group = form.save() + for extra_form in extra_forms: + extra_form.save() + + messages.success(request, _("Nouveau groupe : {}").format(group)) + + return redirect('kfet.group') + else: + form = GroupForm(instance=group) + for extra in extras: + extra['forms'] = [ + form_cls(instance=group, **form_kwargs) + for form_cls, form_kwargs in extra['form_classes'] + ] + + return render(request, 'kfet/group_form.html', { + 'form': form, + 'extras': extras, + }) -class AccountGroupUpdate(AccountGroupFormViewMixin, UpdateView): - success_message = 'Groupe modifié : %(name)s' +@permission_required('kfetauth.change_group') +def group_update(request, pk): + group = get_object_or_404(Group, pk=pk) + + extras = get_group_formview_extras() + + if request.method == 'POST': + form = GroupForm(request.POST, instance=group) + for extra in extras: + extra['forms'] = [ + form_cls( + request.POST, request.FILES, instance=group, **form_kwargs) + for form_cls, form_kwargs in extra['form_classes'] + ] + extra_forms = sum((extra['forms'] for extra in extras), []) + + if form.is_valid() and all(form.is_valid() for form in extra_forms): + group = form.save() + for extra_form in extra_forms: + extra_form.save() + + messages.success(request, _("Groupe modifié : {}").format(group)) + + return redirect('kfet.group') + else: + form = GroupForm(instance=group) + for extra in extras: + extra['forms'] = [ + form_cls(instance=group, **form_kwargs) + for form_cls, form_kwargs in extra['form_classes'] + ] + + return render(request, 'kfet/group_form.html', { + 'form': form, + 'extras': extras, + }) diff --git a/kfet/forms.py b/kfet/forms.py index 8afbe85b..313b0733 100644 --- a/kfet/forms.py +++ b/kfet/forms.py @@ -13,8 +13,6 @@ from kfet.models import ( TransferGroup, Supplier) from gestioncof.models import CofProfile -from .auth.forms import UserGroupForm # noqa - # ----- # Widgets diff --git a/kfet/models.py b/kfet/models.py index 82d769a5..56b4e6a2 100644 --- a/kfet/models.py +++ b/kfet/models.py @@ -101,6 +101,11 @@ class Account(models.Model): def __str__(self): return '%s (%s)' % (self.trigramme, self.name) + def get_absolute_url(self): + return reverse('kfet.account.read', kwargs={ + 'trigramme': self.trigramme, + }) + # Propriétés pour accéder aux attributs de cofprofile et user @property def user(self): diff --git a/kfet/static/kfet/css/base/forms.css b/kfet/static/kfet/css/base/forms.css new file mode 100644 index 00000000..545c9d40 --- /dev/null +++ b/kfet/static/kfet/css/base/forms.css @@ -0,0 +1,52 @@ +.extra-form { + margin-bottom: 15px; +} + + +/* Checkbox select multiple field */ + +.checkbox-select-multiple > ul, +.checkbox-select-multiple > ul > li > ul { + padding-left: 0; + list-style-type: none; +} + +.checkbox-select-multiple label { + font-weight: normal; +} + + +/* Permissions field */ + +.permissions-field > ul { + font-weight: bold; +} + +.permissions-field > ul > li { + margin-bottom: 15px; +} + +.permissions-field > ul > li > ul { + display: flex; + flex-flow: row wrap; + + margin-top: 10px; + padding: 5px 10px 0; + + border: 1px solid #CCC; + border-radius: 3px; + box-shadow: inset 0 1px 1px rgba(0,0,0,.075); +} + +.permissions-field > ul > li > ul > li { + float: left; + flex: 0 1 100%; +} + +.permissions-field > ul > li > ul > li:not(:last-child) { + margin-right: 15px; +} + +@media (min-width: 768px) { + .permissions-field > ul > li > ul > li { flex: 0 1 auto; } +} diff --git a/kfet/static/kfet/css/index.css b/kfet/static/kfet/css/index.css index 8e28cce0..a211cb5e 100644 --- a/kfet/static/kfet/css/index.css +++ b/kfet/static/kfet/css/index.css @@ -8,6 +8,7 @@ /* Base */ @import url("base/misc.css"); @import url("base/buttons.css"); +@import url("base/forms.css"); /* Blocks */ @import url("base/main.css"); @@ -35,6 +36,11 @@ font-weight: bold; } +.header small { + color: #FFF; + opacity: 0.95; +} + .nopadding { padding: 0 !important; } @@ -296,13 +302,6 @@ thead .tooltip { } -/* Checkbox select multiple */ - -.checkbox-select-multiple label { - font-weight: normal; - margin-bottom: 0; -} - /* Statement creation */ .statement-create-summary table { diff --git a/kfet/templates/kfet/account.html b/kfet/templates/kfet/account.html index da98f521..d9abafa3 100644 --- a/kfet/templates/kfet/account.html +++ b/kfet/templates/kfet/account.html @@ -1,4 +1,5 @@ {% extends "kfet/base_col_2.html" %} +{% load i18n %} {% block title %}Comptes{% endblock %} {% block header-title %}Comptes{% endblock %} @@ -23,7 +24,7 @@ {% if perms.kfetauth.view_group %} - Permissions + {% trans "Permissions" %} {% endif %} {% if perms.kfet.view_accountnegative %} diff --git a/kfet/templates/kfet/account_group.html b/kfet/templates/kfet/account_group.html deleted file mode 100644 index 6663bc0e..00000000 --- a/kfet/templates/kfet/account_group.html +++ /dev/null @@ -1,61 +0,0 @@ -{% extends "kfet/base_col_2.html" %} - -{% block title %}Groupes de comptes{% endblock %} -{% block header-title %}Groupes de comptes{% endblock %} - -{% block fixed %} - - - -{% endblock %} - -{% block main %} - -{% for group in groups %} -
-
- {{ group.name }} - -
-
-

Comptes

-
- -
-

Permissions

-
- {% regroup group.permissions.all by content_type as grouped_perms %} -
    - {% for perms_group in grouped_perms %} -
  • - {{ perms_group.grouper|title }} -
      - {% for perm in perms_group.list %} -
    • {{ perm.name }}
    • - {% endfor %} -
    -
  • - {% endfor %} -
-
-
-
-{% endfor %} - -{% endblock %} diff --git a/kfet/templates/kfet/account_group_form.html b/kfet/templates/kfet/account_group_form.html deleted file mode 100644 index f0581b42..00000000 --- a/kfet/templates/kfet/account_group_form.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends 'kfet/base_form.html' %} - -{% block title %}Permissions - Édition{% endblock %} -{% block header-title %}Modification des permissions{% endblock %} - -{% block main %} - -{% include "kfet/form_full_snippet.html" with authz=perms.kfet.manage_perms submit_text="Enregistrer" %} - -{% endblock %} diff --git a/kfet/templates/kfet/form_field_base_snippet.html b/kfet/templates/kfet/form_field_base_snippet.html new file mode 100644 index 00000000..7916f4dd --- /dev/null +++ b/kfet/templates/kfet/form_field_base_snippet.html @@ -0,0 +1,19 @@ +{% load widget_tweaks %} + +{% with widget=field.field.widget %} + +{% if field|widget_type == "checkboxselectmultiple" %} +
+ {{ field }} +
+{% elif field|widget_type == "checkboxinput" %} +
+ +
+{% else %} + {{ field|add_class:'form-control' }} +{% endif %} + +{% endwith %} diff --git a/kfet/templates/kfet/form_field_snippet.html b/kfet/templates/kfet/form_field_snippet.html index 6a4efa16..8177b18a 100644 --- a/kfet/templates/kfet/form_field_snippet.html +++ b/kfet/templates/kfet/form_field_snippet.html @@ -1,26 +1,24 @@ {% load widget_tweaks %}
- -
- {% if field|widget_type == "checkboxselectmultiple" %} -
    - {% for choice in field %} -
  • - -
  • - {% endfor %} -
- {% else %} - {{ field|add_class:'form-control' }} - {% endif %} + {% if not field.label %} + {% elif field|widget_type == "checkboxinput" %} + {# label is displayed along the checkbox #} + {% else %} + + {% endif %} + +
+ + {% include "kfet/form_field_base_snippet.html" with field=field %} + {% if field.errors %} {{ field.errors }} {% endif %} {% if field.help_text %} - {{ field.help_text }} + {{ field.help_text|safe }} {% endif %}
diff --git a/kfet/templates/kfet/form_full_snippet.html b/kfet/templates/kfet/form_full_snippet.html index 79df0cf6..cf834031 100644 --- a/kfet/templates/kfet/form_full_snippet.html +++ b/kfet/templates/kfet/form_full_snippet.html @@ -1,4 +1,4 @@ -
+ {% csrf_token %} {% include "kfet/form_snippet.html" %} {% if not authz %} diff --git a/kfet/templates/kfet/form_snippet.html b/kfet/templates/kfet/form_snippet.html index 2f6d9c7c..9f48cc35 100644 --- a/kfet/templates/kfet/form_snippet.html +++ b/kfet/templates/kfet/form_snippet.html @@ -1,3 +1,5 @@ -{% for field in form %} - {% include 'kfet/form_field_snippet.html' with field=field %} -{% endfor %} +
+ {% for field in form %} + {% include 'kfet/form_field_snippet.html' with field=field %} + {% endfor %} +
diff --git a/kfet/templates/kfet/form_submit_snippet.html b/kfet/templates/kfet/form_submit_snippet.html index fba168da..918153fa 100644 --- a/kfet/templates/kfet/form_submit_snippet.html +++ b/kfet/templates/kfet/form_submit_snippet.html @@ -1,5 +1,11 @@ -
-
- +{% load i18n %} + +{% trans "Enregistrer" as default_value %} + +
+
+
+ +
diff --git a/kfet/tests/test_models.py b/kfet/tests/test_models.py index ea132acd..9cb7ad1a 100644 --- a/kfet/tests/test_models.py +++ b/kfet/tests/test_models.py @@ -12,6 +12,16 @@ class AccountTests(TestCase): self.account = Account(trigramme='000') self.account.save({'username': 'user'}) + def test_get_absolute_url(self): + self.assertEqual( + self.account.get_absolute_url(), '/k-fet/accounts/000') + + account_space = Account(trigramme=' ') + account_space.save({'username': 'space'}) + + self.assertEqual( + account_space.get_absolute_url(), '/k-fet/accounts/%20%20%20') + def test_password(self): self.account.change_pwd('anna') self.account.save() diff --git a/kfet/urls.py b/kfet/urls.py index 192fe24c..350e6a9a 100644 --- a/kfet/urls.py +++ b/kfet/urls.py @@ -8,8 +8,6 @@ from kfet.decorators import teamkfet_required urlpatterns = [ - url(r'^login/generic$', views.login_generic, - name='kfet.login.generic'), url(r'^history$', views.history, name='kfet.history'), @@ -50,19 +48,6 @@ urlpatterns = [ url(r'^accounts/(?P.{3})/edit$', views.account_update, name='kfet.account.update'), - # Account - Groups - url(r'^accounts/groups$', views.account_group, - name='kfet.account.group'), - url(r'^accounts/groups/new$', - permission_required('kfetauth.add_group') - (views.AccountGroupCreate.as_view()), - name='kfet.account.group.create'), - url(r'^accounts/groups/(?P\d+)/edit$', - permission_required('kfetauth.change_group') - (views.AccountGroupUpdate.as_view()), - name='kfet.account.group.update'), - - url(r'^accounts/negatives$', permission_required('kfet.view_accountnegative') (views.AccountNegativeList.as_view()), @@ -245,6 +230,6 @@ urlpatterns = [ ] urlpatterns += [ - # K-Fêt Open urls - url('^open/', include('kfet.open.urls')), + url(r'^', include('kfet.auth.urls')), + url(r'^open/', include('kfet.open.urls')), ] diff --git a/kfet/views.py b/kfet/views.py index bfba8220..6c8adc78 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -24,6 +24,8 @@ from django.utils.decorators import method_decorator from gestioncof.models import CofProfile +from .auth.forms import UserGroupForm + from kfet.config import KFetConfigForm, kfet_config from kfet.decorators import teamkfet_required from kfet.models import ( @@ -33,7 +35,7 @@ from kfet.models import ( TransferGroup, Transfer, ArticleCategory) from kfet.forms import ( AccountTriForm, AccountBalanceForm, AccountNoTriForm, UserForm, CofForm, - UserRestrictTeamForm, UserGroupForm, AccountForm, CofRestrictForm, + UserRestrictTeamForm, AccountForm, CofRestrictForm, AccountPwdForm, AccountNegativeForm, UserRestrictForm, AccountRestrictForm, CheckoutForm, CheckoutRestrictForm, CheckoutStatementCreateForm, CheckoutStatementUpdateForm, ArticleForm, ArticleRestrictForm, @@ -50,10 +52,6 @@ import heapq import statistics from kfet.statistic import ScaleMixin, last_stats_manifest, tot_ventes, WeekScale -from .auth.views import ( # noqa - account_group, login_generic, AccountGroupCreate, AccountGroupUpdate, -) - def put_cleaned_data_in_dict(dict, form): for field in form.cleaned_data: