mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-26 22:52:26 +00:00
Gestion, affichage des clubs, gestion de la recherche
This commit is contained in:
parent
5bdf4d6083
commit
85421a089e
9 changed files with 283 additions and 30 deletions
|
@ -74,20 +74,20 @@ def search_result(search, type, request):
|
|||
recherche = {'users_list': None, 'machines_list' : [], 'facture_list' : None, 'ban_list' : None, 'white_list': None, 'port_list': None, 'switch_list': None}
|
||||
|
||||
if request.user.has_perms(('cableur',)):
|
||||
query = Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search)
|
||||
query = Q(user__pseudo__icontains = search) | Q(user__adherent__name__icontains = search) | Q(user__surname__icontains = search)
|
||||
else:
|
||||
query = (Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search)) & Q(user = request.user)
|
||||
query = (Q(user__pseudo__icontains = search) | Q(user__adherent__name__icontains = search) | Q(user__surname__icontains = search)) & Q(user = request.user)
|
||||
|
||||
|
||||
for i in aff:
|
||||
if i == '0':
|
||||
query_user_list = Q(room__name__icontains = search) | Q(pseudo__icontains = search) | Q(name__icontains = search) | Q(surname__icontains = search) & query1
|
||||
query_user_list = Q(room__name__icontains = search) | Q(pseudo__icontains = search) | Q(adherent__name__icontains = search) | Q(surname__icontains = search) & query1
|
||||
if request.user.has_perms(('cableur',)):
|
||||
recherche['users_list'] = User.objects.filter(query_user_list).order_by('state', 'surname').distinct()
|
||||
else :
|
||||
recherche['users_list'] = User.objects.filter(query_user_list & Q(id=request.user.id)).order_by('state', 'surname').distinct()
|
||||
if i == '1':
|
||||
query_machine_list = Q(machine__user__pseudo__icontains = search) | Q(machine__user__name__icontains = search) | Q(machine__user__surname__icontains = search) | Q(mac_address__icontains = search) | Q(ipv4__ipv4__icontains = search) | Q(domain__name__icontains = search) | Q(domain__related_domain__name__icontains = search)
|
||||
query_machine_list = Q(machine__user__pseudo__icontains = search) | Q(machine__user__adherent__name__icontains = search) | Q(machine__user__surname__icontains = search) | Q(mac_address__icontains = search) | Q(ipv4__ipv4__icontains = search) | Q(domain__name__icontains = search) | Q(domain__related_domain__name__icontains = search)
|
||||
if request.user.has_perms(('cableur',)):
|
||||
data = Interface.objects.filter(query_machine_list).distinct()
|
||||
else:
|
||||
|
|
|
@ -99,7 +99,7 @@ class UserCreationForm(forms.ModelForm):
|
|||
super(UserCreationForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
model = Adherent
|
||||
fields = ('pseudo', 'surname', 'email')
|
||||
|
||||
def clean_password2(self):
|
||||
|
@ -179,7 +179,7 @@ class UserChangeForm(forms.ModelForm):
|
|||
is_admin = forms.BooleanField(label='is admin', required=False)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
model = Adherent
|
||||
fields = ('pseudo', 'password', 'surname', 'email')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -252,13 +252,13 @@ class MassArchiveForm(forms.Form):
|
|||
utilisateurs dont la fin d'accès se situe dans le futur !")
|
||||
|
||||
|
||||
class BaseInfoForm(ModelForm):
|
||||
class NewUserForm(ModelForm):
|
||||
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé
|
||||
pour l'edition de self par self ou un cableur. On formate les champs
|
||||
avec des label plus jolis"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||
super(BaseInfoForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
super(NewUserForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
self.fields['name'].label = 'Prénom'
|
||||
self.fields['surname'].label = 'Nom'
|
||||
self.fields['school'].label = 'Établissement'
|
||||
|
@ -292,13 +292,89 @@ class BaseInfoForm(ModelForm):
|
|||
return telephone
|
||||
|
||||
|
||||
class NewClubForm(ModelForm):
|
||||
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé
|
||||
pour l'edition de self par self ou un cableur. On formate les champs
|
||||
avec des label plus jolis"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||
super(NewClubForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
self.fields['surname'].label = 'Nom'
|
||||
self.fields['school'].label = 'Établissement'
|
||||
self.fields['comment'].label = 'Commentaire'
|
||||
self.fields['room'].label = 'Chambre'
|
||||
self.fields['room'].empty_label = "Pas de chambre"
|
||||
self.fields['school'].empty_label = "Séléctionner un établissement"
|
||||
|
||||
class Meta:
|
||||
model = Club
|
||||
fields = [
|
||||
'surname',
|
||||
'pseudo',
|
||||
'email',
|
||||
'school',
|
||||
'comment',
|
||||
'room',
|
||||
'telephone',
|
||||
]
|
||||
|
||||
def clean_telephone(self):
|
||||
"""Verifie que le tel est présent si 'option est validée
|
||||
dans preferences"""
|
||||
telephone = self.cleaned_data['telephone']
|
||||
preferences, _created = OptionalUser.objects.get_or_create()
|
||||
if not telephone and preferences.is_tel_mandatory:
|
||||
raise forms.ValidationError(
|
||||
"Un numéro de téléphone valide est requis"
|
||||
)
|
||||
return telephone
|
||||
|
||||
|
||||
|
||||
class BaseInfoForm(ModelForm):
|
||||
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé
|
||||
pour l'edition de self par self ou un cableur. On formate les champs
|
||||
avec des label plus jolis"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||
super(BaseInfoForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
self.fields['surname'].label = 'Nom'
|
||||
self.fields['school'].label = 'Établissement'
|
||||
self.fields['comment'].label = 'Commentaire'
|
||||
self.fields['room'].label = 'Chambre'
|
||||
self.fields['room'].empty_label = "Pas de chambre"
|
||||
self.fields['school'].empty_label = "Séléctionner un établissement"
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = [
|
||||
'surname',
|
||||
'pseudo',
|
||||
'email',
|
||||
'school',
|
||||
'comment',
|
||||
'room',
|
||||
'telephone',
|
||||
]
|
||||
|
||||
def clean_telephone(self):
|
||||
"""Verifie que le tel est présent si 'option est validée
|
||||
dans preferences"""
|
||||
telephone = self.cleaned_data['telephone']
|
||||
preferences, _created = OptionalUser.objects.get_or_create()
|
||||
if not telephone and preferences.is_tel_mandatory:
|
||||
raise forms.ValidationError(
|
||||
"Un numéro de téléphone valide est requis"
|
||||
)
|
||||
return telephone
|
||||
|
||||
|
||||
class EditInfoForm(BaseInfoForm):
|
||||
"""Edition complète d'un user. Utilisé par admin,
|
||||
permet d'editer normalement la chambre, ou le shell
|
||||
Herite de la base"""
|
||||
class Meta(BaseInfoForm.Meta):
|
||||
fields = [
|
||||
'name',
|
||||
'surname',
|
||||
'pseudo',
|
||||
'email',
|
||||
|
|
|
@ -149,7 +149,6 @@ class UserManager(BaseUserManager):
|
|||
def _create_user(
|
||||
self,
|
||||
pseudo,
|
||||
name,
|
||||
surname,
|
||||
email,
|
||||
password=None,
|
||||
|
@ -163,7 +162,6 @@ class UserManager(BaseUserManager):
|
|||
|
||||
user = self.model(
|
||||
pseudo=pseudo,
|
||||
name=name,
|
||||
surname=surname,
|
||||
email=self.normalize_email(email),
|
||||
)
|
||||
|
@ -174,19 +172,19 @@ class UserManager(BaseUserManager):
|
|||
user.make_admin()
|
||||
return user
|
||||
|
||||
def create_user(self, pseudo, name, surname, email, password=None):
|
||||
def create_user(self, pseudo, surname, email, password=None):
|
||||
"""
|
||||
Creates and saves a User with the given pseudo, name, surname, email,
|
||||
and password.
|
||||
"""
|
||||
return self._create_user(pseudo, name, surname, email, password, False)
|
||||
return self._create_user(pseudo, surname, email, password, False)
|
||||
|
||||
def create_superuser(self, pseudo, name, surname, email, password):
|
||||
def create_superuser(self, pseudo, surname, email, password):
|
||||
"""
|
||||
Creates and saves a superuser with the given pseudo, name, surname,
|
||||
email, and password.
|
||||
"""
|
||||
return self._create_user(pseudo, name, surname, email, password, True)
|
||||
return self._create_user(pseudo, surname, email, password, True)
|
||||
|
||||
|
||||
class User(AbstractBaseUser):
|
||||
|
@ -246,10 +244,36 @@ class User(AbstractBaseUser):
|
|||
rezo_rez_uid = models.PositiveIntegerField(unique=True, blank=True, null=True)
|
||||
|
||||
USERNAME_FIELD = 'pseudo'
|
||||
REQUIRED_FIELDS = ['name', 'surname', 'email']
|
||||
REQUIRED_FIELDS = ['surname', 'email']
|
||||
|
||||
objects = UserManager()
|
||||
|
||||
@cached_property
|
||||
def name(self):
|
||||
"""Si il s'agit d'un adhérent, on renvoie le prénom"""
|
||||
if self.is_class_adherent:
|
||||
return self.adherent.name
|
||||
else:
|
||||
return ''
|
||||
|
||||
@cached_property
|
||||
def class_name(self):
|
||||
"""Renvoie si il s'agit d'un adhérent ou d'un club"""
|
||||
if hasattr(self, 'adherent'):
|
||||
return "Adhérent"
|
||||
elif hasattr(self, 'club'):
|
||||
return "Club"
|
||||
else:
|
||||
raise NotImplementedError("Type inconnu")
|
||||
|
||||
@cached_property
|
||||
def is_class_club(self):
|
||||
return hasattr(self, 'club')
|
||||
|
||||
@cached_property
|
||||
def is_class_adherent(self):
|
||||
return hasattr(self, 'adherent')
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
""" Renvoie si l'user est à l'état actif"""
|
||||
|
@ -280,11 +304,15 @@ class User(AbstractBaseUser):
|
|||
|
||||
def get_full_name(self):
|
||||
""" Renvoie le nom complet de l'user formaté nom/prénom"""
|
||||
return '%s %s' % (self.name, self.surname)
|
||||
name = self.name
|
||||
if name:
|
||||
return '%s %s' % (name, self.surname)
|
||||
else:
|
||||
return self.surname
|
||||
|
||||
def get_short_name(self):
|
||||
""" Renvoie seulement le nom"""
|
||||
return self.name
|
||||
return self.surname
|
||||
|
||||
def has_perms(self, perms, obj=None):
|
||||
""" Renvoie true si l'user dispose de la permission.
|
||||
|
@ -570,7 +598,7 @@ class User(AbstractBaseUser):
|
|||
.objects.get_or_create()
|
||||
general_options, _created = GeneralOption.objects.get_or_create()
|
||||
context = Context({
|
||||
'nom': str(self.name) + ' ' + str(self.surname),
|
||||
'nom': self.get_full_name(),
|
||||
'asso_name': assooptions.name,
|
||||
'asso_email': assooptions.contact,
|
||||
'welcome_mail_fr': mailmessageoptions.welcome_mail_fr,
|
||||
|
@ -599,7 +627,7 @@ class User(AbstractBaseUser):
|
|||
options, _created = AssoOption.objects.get_or_create()
|
||||
general_options, _created = GeneralOption.objects.get_or_create()
|
||||
context = {
|
||||
'name': str(req.user.name) + ' ' + str(req.user.surname),
|
||||
'name': req.user.get_full_name(),
|
||||
'asso': options.name,
|
||||
'asso_mail': options.contact,
|
||||
'site_name': general_options.site_name,
|
||||
|
@ -929,7 +957,7 @@ class Ban(models.Model):
|
|||
template = loader.get_template('users/email_ban_notif')
|
||||
options, _created = AssoOption.objects.get_or_create()
|
||||
context = Context({
|
||||
'name': str(self.user.name) + ' ' + str(self.user.surname),
|
||||
'name': self.user.get_full_name(),
|
||||
'raison': self.raison,
|
||||
'date_end': self.date_end,
|
||||
'asso_name': options.name,
|
||||
|
|
57
users/templates/users/aff_clubs.html
Normal file
57
users/templates/users/aff_clubs.html
Normal file
|
@ -0,0 +1,57 @@
|
|||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
Copyright © 2017 Gabriel Détraz
|
||||
Copyright © 2017 Goulven Kermarec
|
||||
Copyright © 2017 Augustin Lemesle
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
{% endcomment %}
|
||||
|
||||
{% if clubs_list.paginator %}
|
||||
{% include "pagination.html" with list=clubs_list %}
|
||||
{% endif %}
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% include "buttons/sort.html" with prefix='club' col="surname" text="Nom" %}</th>
|
||||
<th>{% include "buttons/sort.html" with prefix='club' col="pseudo" text="Pseudo" %}</th>
|
||||
<th>{% include "buttons/sort.html" with prefix='club' col="room" text="Chambre" %}</th>
|
||||
<th>Fin de cotisation le</th>
|
||||
<th>Connexion</th>
|
||||
<th>Profil</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for club in clubs_list %}
|
||||
<tr>
|
||||
<td>{{ club.surname }}</td>
|
||||
<td>{{ club.pseudo }}</td>
|
||||
<td>{{ club.room }}</td>
|
||||
<td>{% if club.is_adherent %}{{ club.end_adhesion }}{% else %}Non adhérent{% endif %}</td>
|
||||
<td>{% if club.has_access == True %}
|
||||
<font color="green">Active</font>
|
||||
{% else %}
|
||||
<font color="red">Désactivée</font>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a href="{% url "users:profil" club.id%}" class="btn btn-primary btn-sm" role="button"><i class="glyphicon glyphicon-user"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
37
users/templates/users/index_clubs.html
Normal file
37
users/templates/users/index_clubs.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
{% extends "users/sidebar.html" %}
|
||||
{% comment %}
|
||||
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
se veut agnostique au réseau considéré, de manière à être installable en
|
||||
quelques clics.
|
||||
|
||||
Copyright © 2017 Gabriel Détraz
|
||||
Copyright © 2017 Goulven Kermarec
|
||||
Copyright © 2017 Augustin Lemesle
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
{% endcomment %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block title %}Utilisateurs{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Clubs</h2>
|
||||
{% include "users/aff_clubs.html" with clubs_list=clubs_list %}
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
{% endblock %}
|
||||
|
|
@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
{% block title %}Profil{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Adhérent</h2>
|
||||
<h2>{{ user.class_name }}</h2>
|
||||
<div>
|
||||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-info' user.id %}">
|
||||
<i class="glyphicon glyphicon-edit"></i>
|
||||
|
|
|
@ -30,9 +30,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
<i class="glyphicon glyphicon-plus"></i>
|
||||
Créer un adhérent
|
||||
</a>
|
||||
<a class="list-group-item list-group-item-success" href="{% url "users:new-club" %}">
|
||||
<i class="glyphicon glyphicon-plus"></i>
|
||||
Créer un club/association
|
||||
</a>
|
||||
<a class="list-group-item list-group-item-info" href="{% url "users:index" %}">
|
||||
<i class="glyphicon glyphicon-list"></i>
|
||||
Adhérents
|
||||
Adherents
|
||||
</a>
|
||||
<a class="list-group-item list-group-item-info" href="{% url "users:index-clubs" %}">
|
||||
<i class="glyphicon glyphicon-list"></i>
|
||||
Clubs
|
||||
</a>
|
||||
<a class="list-group-item list-group-item-info" href="{% url "users:index-ban" %}">
|
||||
<i class="glyphicon glyphicon-list"></i>
|
||||
|
|
|
@ -31,6 +31,7 @@ from . import views
|
|||
|
||||
urlpatterns = [
|
||||
url(r'^new_user/$', views.new_user, name='new-user'),
|
||||
url(r'^new_club/$', views.new_club, name='new-club'),
|
||||
url(r'^edit_info/(?P<userid>[0-9]+)$', views.edit_info, name='edit-info'),
|
||||
url(r'^state/(?P<userid>[0-9]+)$', views.state, name='state'),
|
||||
url(r'^password/(?P<userid>[0-9]+)$', views.password, name='password'),
|
||||
|
@ -118,5 +119,6 @@ urlpatterns = [
|
|||
name='history'
|
||||
),
|
||||
url(r'^$', views.index, name='index'),
|
||||
url(r'^index_clubs/$', views.index_clubs, name='index-clubs'),
|
||||
url(r'^rest/mailing/$', views.mailing, name='mailing'),
|
||||
]
|
||||
|
|
|
@ -58,7 +58,7 @@ from users.forms import DelRightForm, BanForm, WhitelistForm, DelSchoolForm
|
|||
from users.forms import DelListRightForm, NewListRightForm
|
||||
from users.forms import InfoForm, BaseInfoForm, StateForm
|
||||
from users.forms import RightForm, SchoolForm, EditServiceUserForm
|
||||
from users.forms import ServiceUserForm, ListRightForm
|
||||
from users.forms import ServiceUserForm, ListRightForm, NewUserForm, NewClubForm
|
||||
from users.forms import MassArchiveForm, PassForm, ResetPasswordForm
|
||||
from cotisations.models import Facture
|
||||
from machines.models import Machine
|
||||
|
@ -85,7 +85,7 @@ def password_change_action(u_form, user, request, req=False):
|
|||
def new_user(request):
|
||||
""" Vue de création d'un nouvel utilisateur,
|
||||
envoie un mail pour le mot de passe"""
|
||||
user = InfoForm(request.POST or None)
|
||||
user = NewUserForm(request.POST or None)
|
||||
if user.is_valid():
|
||||
user = user.save(commit=False)
|
||||
with transaction.atomic(), reversion.create_revision():
|
||||
|
@ -99,6 +99,25 @@ def new_user(request):
|
|||
return form({'userform': user}, 'users/user.html', request)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def new_club(request):
|
||||
""" Vue de création d'un nouveau club,
|
||||
envoie un mail pour le mot de passe"""
|
||||
club = NewClubForm(request.POST or None)
|
||||
if club.is_valid():
|
||||
club = club.save(commit=False)
|
||||
with transaction.atomic(), reversion.create_revision():
|
||||
club.save()
|
||||
reversion.set_user(request.user)
|
||||
reversion.set_comment("Création")
|
||||
club.reset_passwd_mail(request)
|
||||
messages.success(request, "L'utilisateur %s a été crée, un mail\
|
||||
pour l'initialisation du mot de passe a été envoyé" % club.pseudo)
|
||||
return redirect("/users/profil/" + str(club.id))
|
||||
return form({'userform': club}, 'users/user.html', request)
|
||||
|
||||
|
||||
@login_required
|
||||
def edit_info(request, userid):
|
||||
""" Edite un utilisateur à partir de son id,
|
||||
|
@ -572,10 +591,10 @@ def mass_archive(request):
|
|||
@login_required
|
||||
@permission_required('cableur')
|
||||
def index(request):
|
||||
""" Affiche l'ensemble des users, need droit cableur """
|
||||
""" Affiche l'ensemble des adherents, need droit cableur """
|
||||
options, _created = GeneralOption.objects.get_or_create()
|
||||
pagination_number = options.pagination_number
|
||||
users_list = User.objects.select_related('room')
|
||||
users_list = Adherent.objects.select_related('room')
|
||||
users_list = SortTable.sort(
|
||||
users_list,
|
||||
request.GET.get('col'),
|
||||
|
@ -595,6 +614,32 @@ def index(request):
|
|||
return render(request, 'users/index.html', {'users_list': users_list})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def index_clubs(request):
|
||||
""" Affiche l'ensemble des clubs, need droit cableur """
|
||||
options, _created = GeneralOption.objects.get_or_create()
|
||||
pagination_number = options.pagination_number
|
||||
clubs_list = Club.objects.select_related('room')
|
||||
clubs_list = SortTable.sort(
|
||||
clubs_list,
|
||||
request.GET.get('col'),
|
||||
request.GET.get('order'),
|
||||
SortTable.USERS_INDEX
|
||||
)
|
||||
paginator = Paginator(clubs_list, pagination_number)
|
||||
page = request.GET.get('page')
|
||||
try:
|
||||
clubs_list = paginator.page(page)
|
||||
except PageNotAnInteger:
|
||||
# If page is not an integer, deliver first page.
|
||||
clubs_list = paginator.page(1)
|
||||
except EmptyPage:
|
||||
# If page is out of range (e.g. 9999), deliver last page of results.
|
||||
clubs_list = paginator.page(paginator.num_pages)
|
||||
return render(request, 'users/index_clubs.html', {'clubs_list': clubs_list})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def index_ban(request):
|
||||
|
|
Loading…
Reference in a new issue