mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-21 01:48:21 +02:00
Better tables
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models import WEIClub, Bus, BusTeam
|
||||
from ..models import WEIClub, Bus, BusTeam, WEIRole, WEIRegistration, WEIMembership
|
||||
|
||||
|
||||
class WEIClubSerializer(serializers.ModelSerializer):
|
||||
@ -37,3 +37,36 @@ class BusTeamSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = BusTeam
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class WEIRoleSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for WEI roles.
|
||||
The djangorestframework plugin will analyse the model `WEIRole` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = WEIRole
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class WEIRegistrationSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for WEI registrations.
|
||||
The djangorestframework plugin will analyse the model `WEIRegistration` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = WEIRegistration
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class WEIMembershipSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for WEI memberships.
|
||||
The djangorestframework plugin will analyse the model `WEIMembership` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = WEIMembership
|
||||
fields = '__all__'
|
||||
|
@ -1,7 +1,8 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .views import WEIClubViewSet, BusViewSet, BusTeamViewSet
|
||||
from .views import WEIClubViewSet, BusViewSet, BusTeamViewSet, WEIRoleViewSet, WEIRegistrationViewSet, \
|
||||
WEIMembershipViewSet
|
||||
|
||||
|
||||
def register_wei_urls(router, path):
|
||||
@ -11,3 +12,6 @@ def register_wei_urls(router, path):
|
||||
router.register(path + '/club', WEIClubViewSet)
|
||||
router.register(path + '/bus', BusViewSet)
|
||||
router.register(path + '/team', BusTeamViewSet)
|
||||
router.register(path + '/role', WEIRoleViewSet)
|
||||
router.register(path + '/registration', WEIRegistrationViewSet)
|
||||
router.register(path + '/membership', WEIMembershipViewSet)
|
||||
|
@ -4,8 +4,9 @@ from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework.filters import SearchFilter
|
||||
from api.viewsets import ReadProtectedModelViewSet
|
||||
|
||||
from .serializers import WEIClubSerializer, BusSerializer, BusTeamSerializer
|
||||
from ..models import WEIClub, Bus, BusTeam
|
||||
from .serializers import WEIClubSerializer, BusSerializer, BusTeamSerializer, WEIRoleSerializer, \
|
||||
WEIRegistrationSerializer, WEIMembershipSerializer
|
||||
from ..models import WEIClub, Bus, BusTeam, WEIRole, WEIRegistration, WEIMembership
|
||||
|
||||
|
||||
class WEIClubViewSet(ReadProtectedModelViewSet):
|
||||
@ -27,7 +28,7 @@ class BusViewSet(ReadProtectedModelViewSet):
|
||||
The djangorestframework plugin will get all `Bus` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/wei/bus/
|
||||
"""
|
||||
queryset = Bus.objects.all()
|
||||
queryset = Bus.objects
|
||||
serializer_class = BusSerializer
|
||||
filter_backends = [SearchFilter, DjangoFilterBackend]
|
||||
search_fields = ['$name', ]
|
||||
@ -40,8 +41,46 @@ class BusTeamViewSet(ReadProtectedModelViewSet):
|
||||
The djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/wei/team/
|
||||
"""
|
||||
queryset = BusTeam.objects.all()
|
||||
queryset = BusTeam.objects
|
||||
serializer_class = BusTeamSerializer
|
||||
filter_backends = [SearchFilter, DjangoFilterBackend]
|
||||
search_fields = ['$name', ]
|
||||
filterset_fields = ['name', 'bus', 'bus__wei', ]
|
||||
|
||||
|
||||
class WEIRoleViewSet(ReadProtectedModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all `WEIRole` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/wei/role/
|
||||
"""
|
||||
queryset = WEIRole.objects
|
||||
serializer_class = WEIRoleSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$name', ]
|
||||
|
||||
|
||||
class WEIRegistrationViewSet(ReadProtectedModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all WEIRegistration objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/wei/registration/
|
||||
"""
|
||||
queryset = WEIRegistration.objects
|
||||
serializer_class = WEIRegistrationSerializer
|
||||
filter_backends = [SearchFilter, DjangoFilterBackend]
|
||||
search_fields = ['$user__username', ]
|
||||
filterset_fields = ['user', 'wei', ]
|
||||
|
||||
|
||||
class WEIMembershipViewSet(ReadProtectedModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/wei/membership/
|
||||
"""
|
||||
queryset = WEIMembership.objects
|
||||
serializer_class = WEIMembershipSerializer
|
||||
filter_backends = [SearchFilter, DjangoFilterBackend]
|
||||
search_fields = ['$user__username', '$bus__name', '$team__name', ]
|
||||
filterset_fields = ['user', 'club', 'bus', 'team', ]
|
||||
|
@ -77,7 +77,7 @@ class WEIRegistrationTable(tables.Table):
|
||||
}
|
||||
model = WEIRegistration
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
fields = ('user', 'first_year',)
|
||||
fields = ('user', 'user.first_name', 'user.last_name', 'first_year',)
|
||||
row_attrs = {
|
||||
'class': 'table-row',
|
||||
'id': lambda record: "row-" + str(record.pk),
|
||||
@ -86,13 +86,28 @@ class WEIRegistrationTable(tables.Table):
|
||||
|
||||
|
||||
class WEIMembershipTable(tables.Table):
|
||||
user = tables.LinkColumn(
|
||||
'wei:wei_update_registration',
|
||||
args=[A('registration.pk')],
|
||||
)
|
||||
|
||||
bus = tables.LinkColumn(
|
||||
'wei:manage_bus',
|
||||
args=[A('bus.pk')],
|
||||
)
|
||||
|
||||
team = tables.LinkColumn(
|
||||
'wei:manage_bus_team',
|
||||
args=[A('bus.pk')],
|
||||
)
|
||||
|
||||
class Meta:
|
||||
attrs = {
|
||||
'class': 'table table-condensed table-striped table-hover'
|
||||
}
|
||||
model = WEIMembership
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
fields = ('user', )
|
||||
fields = ('user', 'user.first_name', 'user.last_name', 'bus', 'team', )
|
||||
row_attrs = {
|
||||
'class': 'table-row',
|
||||
'id': lambda record: "row-" + str(record.pk),
|
||||
|
@ -4,6 +4,7 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import CurrentWEIDetailView, WEIListView, WEICreateView, WEIDetailView, WEIUpdateView,\
|
||||
WEIRegistrationsView, WEIMembershipsView,\
|
||||
BusCreateView, BusManageView, BusUpdateView, BusTeamCreateView, BusTeamManageView, BusTeamUpdateView,\
|
||||
WEIRegister1AView, WEIRegister2AView, WEIUpdateRegistrationView, WEIDeleteRegistrationView,\
|
||||
WEIValidateRegistrationView, WEISurveyView, WEISurveyEndView, WEIClosedView
|
||||
@ -16,6 +17,8 @@ urlpatterns = [
|
||||
path('create/', WEICreateView.as_view(), name="wei_create"),
|
||||
path('detail/<int:pk>/', WEIDetailView.as_view(), name="wei_detail"),
|
||||
path('update/<int:pk>/', WEIUpdateView.as_view(), name="wei_update"),
|
||||
path('detail/<int:pk>/registrations/', WEIRegistrationsView.as_view(), name="wei_registrations"),
|
||||
path('detail/<int:pk>/memberships/', WEIMembershipsView.as_view(), name="wei_memberships"),
|
||||
path('add-bus/<int:pk>/', BusCreateView.as_view(), name="add_bus"),
|
||||
path('manage-bus/<int:pk>/', BusManageView.as_view(), name="manage_bus"),
|
||||
path('update-bus/<int:pk>/', BusUpdateView.as_view(), name="update_bus"),
|
||||
|
@ -5,6 +5,7 @@ from datetime import datetime, date
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db.models import Q
|
||||
from django.forms import HiddenInput
|
||||
from django.shortcuts import redirect
|
||||
@ -14,7 +15,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.edit import BaseFormView, DeleteView
|
||||
from django_tables2 import SingleTableView
|
||||
from member.models import Membership, Club
|
||||
from note.models import Transaction, NoteClub
|
||||
from note.models import Transaction, NoteClub, Alias
|
||||
from note.tables import HistoryTable
|
||||
from permission.backends import PermissionBackend
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
@ -128,6 +129,78 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
|
||||
return context
|
||||
|
||||
|
||||
class WEIMembershipsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
"""
|
||||
List all WEI memberships
|
||||
"""
|
||||
model = WEIMembership
|
||||
table_class = WEIMembershipTable
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
qs = super().get_queryset(**kwargs).filter(club=self.club)
|
||||
|
||||
pattern = self.request.GET.get("search", "")
|
||||
|
||||
if not pattern:
|
||||
return qs.none()
|
||||
|
||||
qs = qs.filter(
|
||||
Q(user__first_name__iregex=pattern)
|
||||
| Q(user__last_name__iregex=pattern)
|
||||
| Q(user__note__alias__name__iregex="^" + pattern)
|
||||
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||
| Q(bus__name__iregex=pattern)
|
||||
| Q(team__name__iregex=pattern)
|
||||
)
|
||||
|
||||
return qs[:20]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["club"] = self.club
|
||||
context["title"] = _("Find WEI Membership")
|
||||
return context
|
||||
|
||||
|
||||
class WEIRegistrationsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
"""
|
||||
List all non-validated WEI registrations.
|
||||
"""
|
||||
model = WEIRegistration
|
||||
table_class = WEIRegistrationTable
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.club = WEIClub.objects.get(pk=self.kwargs["pk"])
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self, **kwargs):
|
||||
qs = super().get_queryset(**kwargs).filter(wei=self.club, membership=None)
|
||||
|
||||
pattern = self.request.GET.get("search", "")
|
||||
|
||||
if not pattern:
|
||||
return qs.none()
|
||||
|
||||
qs = qs.filter(
|
||||
Q(user__first_name__iregex=pattern)
|
||||
| Q(user__last_name__iregex=pattern)
|
||||
| Q(user__note__alias__name__iregex="^" + pattern)
|
||||
| Q(user__note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||
)
|
||||
|
||||
return qs[:20]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["club"] = self.club
|
||||
context["title"] = _("Find WEI Registration")
|
||||
return context
|
||||
|
||||
|
||||
class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
||||
"""
|
||||
Update the information of the WEI.
|
||||
@ -494,7 +567,7 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
del form.fields["user"]
|
||||
form.fields["user"].disabled = True
|
||||
if not self.object.first_year:
|
||||
del form.fields["information_json"]
|
||||
return form
|
||||
@ -502,7 +575,7 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
def form_valid(self, form):
|
||||
# If the membership is already validated, then we update the bus and the team (and the roles)
|
||||
if form.instance.is_validated:
|
||||
membership_form = WEIMembershipForm(self.request.POST)
|
||||
membership_form = WEIMembershipForm(self.request.POST, instance=form.instance.membership)
|
||||
if not membership_form.is_valid():
|
||||
return self.form_invalid(form)
|
||||
membership_form.save()
|
||||
@ -534,14 +607,22 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
|
||||
|
||||
|
||||
class WEIDeleteRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView):
|
||||
"""
|
||||
Delete a non-validated WEI registration
|
||||
"""
|
||||
model = WEIRegistration
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
wei = self.get_object().wei
|
||||
object = self.get_object()
|
||||
wei = object.wei
|
||||
today = date.today()
|
||||
# We can't delete a registration of a past WEI
|
||||
if today > wei.membership_end:
|
||||
return redirect(reverse_lazy('wei:wei_closed', args=(wei.pk,)))
|
||||
|
||||
if not PermissionBackend.check_perm(self.request.user, "wei.delete_weiregistration", object):
|
||||
raise PermissionDenied
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
Reference in New Issue
Block a user