Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

Commit 57592353 authored by Chirac's avatar Chirac

Merge branch 'master' into 'massive_use_bft_tag'

# Conflicts:
#   topologie/views.py
parents 95c32b46 dc3096a3
......@@ -4,3 +4,4 @@ settings_local.py
re2o.png
__pycache__/*
static_files/*
static/logo/*
......@@ -28,23 +28,37 @@ from reversion.admin import VersionAdmin
from .models import Facture, Article, Banque, Paiement, Cotisation, Vente
class FactureAdmin(VersionAdmin):
list_display = ('user','paiement','date','valid','control')
"""Class admin d'une facture, tous les champs"""
pass
class VenteAdmin(VersionAdmin):
list_display = ('facture','name','prix','number','iscotisation','duration')
"""Class admin d'une vente, tous les champs (facture related)"""
pass
class ArticleAdmin(VersionAdmin):
list_display = ('name','prix','iscotisation','duration')
"""Class admin d'un article en vente"""
pass
class BanqueAdmin(VersionAdmin):
list_display = ('name',)
"""Class admin de la liste des banques (facture related)"""
pass
class PaiementAdmin(VersionAdmin):
list_display = ('moyen','type_paiement')
"""Class admin d'un moyen de paiement (facture related"""
pass
class CotisationAdmin(VersionAdmin):
list_display = ('vente','date_start','date_end')
"""Class admin d'une cotisation (date de debut et de fin),
Vente related"""
pass
admin.site.register(Facture, FactureAdmin)
admin.site.register(Article, ArticleAdmin)
......
......@@ -19,16 +19,33 @@
# 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.
"""
Forms de l'application cotisation de re2o. Dépendance avec les models,
importé par les views.
Permet de créer une nouvelle facture pour un user (NewFactureForm),
et de l'editer (soit l'user avec EditFactureForm,
soit le trésorier avec TrezEdit qui a plus de possibilités que self
notamment sur le controle trésorier)
SelectArticleForm est utilisée lors de la creation d'une facture en
parrallèle de NewFacture pour le choix des articles désirés.
(la vue correspondante est unique)
ArticleForm, BanqueForm, PaiementForm permettent aux admin d'ajouter,
éditer ou supprimer une banque/moyen de paiement ou un article
"""
from __future__ import unicode_literals
from django import forms
from django.forms import ModelForm, Form
from django import forms
from django.core.validators import MinValueValidator
from .models import Article, Paiement, Facture, Banque, Vente
from .models import Article, Paiement, Facture, Banque
class NewFactureForm(ModelForm):
"""Creation d'une facture, moyen de paiement, banque et numero
de cheque"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(NewFactureForm, self).__init__(*args, prefix=prefix, **kwargs)
......@@ -36,58 +53,91 @@ class NewFactureForm(ModelForm):
self.fields['banque'].required = False
self.fields['cheque'].label = 'Numero de chèque'
self.fields['banque'].empty_label = "Non renseigné"
self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement"
self.fields['paiement'].widget.attrs['data-cheque'] = Paiement.objects.filter(type_paiement=1).first().id
self.fields['paiement'].empty_label = "Séléctionner\
un moyen de paiement"
self.fields['paiement'].widget.attrs['data-cheque'] = Paiement.objects\
.filter(type_paiement=1).first().id
class Meta:
model = Facture
fields = ['paiement','banque','cheque']
fields = ['paiement', 'banque', 'cheque']
def clean(self):
cleaned_data=super(NewFactureForm, self).clean()
cleaned_data = super(NewFactureForm, self).clean()
paiement = cleaned_data.get("paiement")
cheque = cleaned_data.get("cheque")
banque = cleaned_data.get("banque")
if not paiement:
raise forms.ValidationError("Le moyen de paiement est obligatoire.")
raise forms.ValidationError("Le moyen de paiement est obligatoire")
elif paiement.type_paiement == "check" and not (cheque and banque):
raise forms.ValidationError("Le numéro de chèque et la banque sont obligatoires.")
raise forms.ValidationError("Le numéro de chèque et\
la banque sont obligatoires.")
return cleaned_data
class CreditSoldeForm(NewFactureForm):
"""Permet de faire des opérations sur le solde si il est activé"""
class Meta(NewFactureForm.Meta):
model = Facture
fields = ['paiement','banque','cheque']
fields = ['paiement', 'banque', 'cheque']
def __init__(self, *args, **kwargs):
super(CreditSoldeForm, self).__init__(*args, **kwargs)
self.fields['paiement'].queryset = Paiement.objects.exclude(moyen='solde').exclude(moyen="Solde")
self.fields['paiement'].queryset = Paiement.objects.exclude(
moyen='solde'
).exclude(moyen="Solde")
montant = forms.DecimalField(max_digits=5, decimal_places=2, required=True)
class SelectArticleForm(Form):
article = forms.ModelChoiceField(queryset=Article.objects.all(), label="Article", required=True)
quantity = forms.IntegerField(label="Quantité", validators=[MinValueValidator(1)], required=True)
"""Selection d'un article lors de la creation d'une facture"""
article = forms.ModelChoiceField(
queryset=Article.objects.all(),
label="Article",
required=True
)
quantity = forms.IntegerField(
label="Quantité",
validators=[MinValueValidator(1)],
required=True
)
class NewFactureFormPdf(Form):
article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article")
number = forms.IntegerField(label="Quantité", validators=[MinValueValidator(1)])
"""Creation d'un pdf facture par le trésorier"""
article = forms.ModelMultipleChoiceField(
queryset=Article.objects.all(),
label="Article"
)
number = forms.IntegerField(
label="Quantité",
validators=[MinValueValidator(1)]
)
paid = forms.BooleanField(label="Payé", required=False)
dest = forms.CharField(required=True, max_length=255, label="Destinataire")
chambre = forms.CharField(required=False, max_length=10, label="Adresse")
fid = forms.CharField(required=True, max_length=10, label="Numéro de la facture")
fid = forms.CharField(
required=True,
max_length=10,
label="Numéro de la facture"
)
class EditFactureForm(NewFactureForm):
"""Edition d'une facture : moyen de paiement, banque, user parent"""
class Meta(NewFactureForm.Meta):
fields = ['paiement','banque','cheque','user']
fields = ['paiement', 'banque', 'cheque', 'user']
def __init__(self, *args, **kwargs):
super(EditFactureForm, self).__init__(*args, **kwargs)
self.fields['user'].label = 'Adherent'
self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire"
self.fields['user'].empty_label = "Séléctionner\
l'adhérent propriétaire"
class TrezEditFactureForm(EditFactureForm):
"""Vue pour édition controle trésorier"""
class Meta(EditFactureForm.Meta):
fields = '__all__'
......@@ -98,6 +148,7 @@ class TrezEditFactureForm(EditFactureForm):
class ArticleForm(ModelForm):
"""Creation d'un article. Champs : nom, cotisation, durée"""
class Meta:
model = Article
fields = '__all__'
......@@ -107,10 +158,20 @@ class ArticleForm(ModelForm):
super(ArticleForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = "Désignation de l'article"
class DelArticleForm(Form):
articles = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Articles actuels", widget=forms.CheckboxSelectMultiple)
"""Suppression d'un ou plusieurs articles en vente. Choix
parmis les modèles"""
articles = forms.ModelMultipleChoiceField(
queryset=Article.objects.all(),
label="Articles actuels",
widget=forms.CheckboxSelectMultiple
)
class PaiementForm(ModelForm):
"""Creation d'un moyen de paiement, champ text moyen et type
permettant d'indiquer si il s'agit d'un chèque ou non pour le form"""
class Meta:
model = Paiement
fields = ['moyen', 'type_paiement']
......@@ -121,10 +182,19 @@ class PaiementForm(ModelForm):
self.fields['moyen'].label = 'Moyen de paiement à ajouter'
self.fields['type_paiement'].label = 'Type de paiement à ajouter'
class DelPaiementForm(Form):
paiements = forms.ModelMultipleChoiceField(queryset=Paiement.objects.all(), label="Moyens de paiement actuels", widget=forms.CheckboxSelectMultiple)
"""Suppression d'un ou plusieurs moyens de paiements, selection
parmis les models"""
paiements = forms.ModelMultipleChoiceField(
queryset=Paiement.objects.all(),
label="Moyens de paiement actuels",
widget=forms.CheckboxSelectMultiple
)
class BanqueForm(ModelForm):
"""Creation d'une banque, field name"""
class Meta:
model = Banque
fields = ['name']
......@@ -134,5 +204,11 @@ class BanqueForm(ModelForm):
super(BanqueForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = 'Banque à ajouter'
class DelBanqueForm(Form):
banques = forms.ModelMultipleChoiceField(queryset=Banque.objects.all(), label="Banques actuelles", widget=forms.CheckboxSelectMultiple)
"""Selection d'une ou plusieurs banques, pour suppression"""
banques = forms.ModelMultipleChoiceField(
queryset=Banque.objects.all(),
label="Banques actuelles",
widget=forms.CheckboxSelectMultiple
)
This diff is collapsed.
......@@ -27,30 +27,96 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^new_facture/(?P<userid>[0-9]+)$', views.new_facture, name='new-facture'),
url(r'^edit_facture/(?P<factureid>[0-9]+)$', views.edit_facture, name='edit-facture'),
url(r'^del_facture/(?P<factureid>[0-9]+)$', views.del_facture, name='del-facture'),
url(r'^facture_pdf/(?P<factureid>[0-9]+)$', views.facture_pdf, name='facture-pdf'),
url(r'^new_facture_pdf/$', views.new_facture_pdf, name='new-facture-pdf'),
url(r'^credit_solde/(?P<userid>[0-9]+)$', views.credit_solde, name='credit-solde'),
url(r'^add_article/$', views.add_article, name='add-article'),
url(r'^edit_article/(?P<articleid>[0-9]+)$', views.edit_article, name='edit-article'),
url(r'^del_article/$', views.del_article, name='del-article'),
url(r'^add_paiement/$', views.add_paiement, name='add-paiement'),
url(r'^edit_paiement/(?P<paiementid>[0-9]+)$', views.edit_paiement, name='edit-paiement'),
url(r'^del_paiement/$', views.del_paiement, name='del-paiement'),
url(r'^add_banque/$', views.add_banque, name='add-banque'),
url(r'^edit_banque/(?P<banqueid>[0-9]+)$', views.edit_banque, name='edit-banque'),
url(r'^del_banque/$', views.del_banque, name='del-banque'),
url(r'^index_article/$', views.index_article, name='index-article'),
url(r'^index_banque/$', views.index_banque, name='index-banque'),
url(r'^index_paiement/$', views.index_paiement, name='index-paiement'),
url(r'^history/(?P<object>facture)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>article)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>paiement)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>banque)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^control/$', views.control, name='control'),
url(r'^new_facture/(?P<userid>[0-9]+)$',
views.new_facture,
name='new-facture'
),
url(r'^edit_facture/(?P<factureid>[0-9]+)$',
views.edit_facture,
name='edit-facture'
),
url(r'^del_facture/(?P<factureid>[0-9]+)$',
views.del_facture,
name='del-facture'
),
url(r'^facture_pdf/(?P<factureid>[0-9]+)$',
views.facture_pdf,
name='facture-pdf'
),
url(r'^new_facture_pdf/$',
views.new_facture_pdf,
name='new-facture-pdf'
),
url(r'^credit_solde/(?P<userid>[0-9]+)$',
views.credit_solde,
name='credit-solde'
),
url(r'^add_article/$',
views.add_article,
name='add-article'
),
url(r'^edit_article/(?P<articleid>[0-9]+)$',
views.edit_article,
name='edit-article'
),
url(r'^del_article/$',
views.del_article,
name='del-article'
),
url(r'^add_paiement/$',
views.add_paiement,
name='add-paiement'
),
url(r'^edit_paiement/(?P<paiementid>[0-9]+)$',
views.edit_paiement,
name='edit-paiement'
),
url(r'^del_paiement/$',
views.del_paiement,
name='del-paiement'
),
url(r'^add_banque/$',
views.add_banque,
name='add-banque'
),
url(r'^edit_banque/(?P<banqueid>[0-9]+)$',
views.edit_banque,
name='edit-banque'
),
url(r'^del_banque/$',
views.del_banque,
name='del-banque'
),
url(r'^index_article/$',
views.index_article,
name='index-article'
),
url(r'^index_banque/$',
views.index_banque,
name='index-banque'
),
url(r'^index_paiement/$',
views.index_paiement,
name='index-paiement'
),
url(r'^history/(?P<object>facture)/(?P<id>[0-9]+)$',
views.history,
name='history'
),
url(r'^history/(?P<object>article)/(?P<id>[0-9]+)$',
views.history,
name='history'
),
url(r'^history/(?P<object>paiement)/(?P<id>[0-9]+)$',
views.history,
name='history'),
url(r'^history/(?P<object>banque)/(?P<id>[0-9]+)$',
views.history,
name='history'
),
url(r'^control/$',
views.control,
name='control'
),
url(r'^$', views.index, name='index'),
]
This diff is collapsed.
......@@ -3,6 +3,7 @@
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyirght © 2017 Daniel Stan
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
......@@ -30,20 +31,18 @@ moment de l'authentification, en WiFi, filaire, ou par les NAS eux-mêmes.
Inspirés d'autres exemples trouvés ici :
https://github.com/FreeRADIUS/freeradius-server/blob/master/src/modules/rlm_python/
Inspiré du travail de Daniel Stan au Crans
"""
import logging
import netaddr
import radiusd # Module magique freeradius (radiusd.py is dummy)
import os
import binascii
import hashlib
import os, sys
import os, sys
proj_path = "/var/www/re2o/"
# This is so Django knows where to find stuff.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
......
......@@ -29,9 +29,9 @@ from django.template import Context, RequestContext, loader
from preferences.models import Service
def form(ctx, template, request):
c = ctx
c.update(csrf(request))
return render(request, template, c)
context = ctx
context.update(csrf(request))
return render(request, template, context)
def index(request):
......
......@@ -20,6 +20,9 @@
# 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.
"""
Fichier définissant les administration des models dans l'interface admin
"""
from __future__ import unicode_literals
......@@ -28,18 +31,27 @@ from reversion.admin import VersionAdmin
from .models import Port, Room, Switch, Stack
class StackAdmin(VersionAdmin):
"""Administration d'une stack de switches (inclus des switches)"""
pass
class SwitchAdmin(VersionAdmin):
"""Administration d'un switch"""
pass
class PortAdmin(VersionAdmin):
"""Administration d'un port de switches"""
pass
class RoomAdmin(VersionAdmin):
"""Administration d'un chambre"""
pass
admin.site.register(Port, PortAdmin)
admin.site.register(Room, RoomAdmin)
admin.site.register(Switch, SwitchAdmin)
......
......@@ -19,14 +19,27 @@
# 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.
"""
Un forms le plus simple possible pour les objets topologie de re2o.
Permet de créer et supprimer : un Port de switch, relié à un switch.
Permet de créer des stacks et d'y ajouter des switchs (StackForm)
Permet de créer, supprimer et editer un switch (EditSwitchForm,
NewSwitchForm)
"""
from __future__ import unicode_literals
from .models import Port, Switch, Room, Stack
from django.forms import ModelForm, Form
from machines.models import Interface
from django.forms import ModelForm
from .models import Port, Switch, Room, Stack
class PortForm(ModelForm):
"""Formulaire pour la création d'un port d'un switch
Relié directement au modèle port"""
class Meta:
model = Port
fields = '__all__'
......@@ -35,25 +48,45 @@ class PortForm(ModelForm):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(PortForm, self).__init__(*args, prefix=prefix, **kwargs)
class EditPortForm(ModelForm):
"""Form pour l'édition d'un port de switche : changement des reglages
radius ou vlan, ou attribution d'une chambre, autre port ou machine
Un port est relié à une chambre, un autre port (uplink) ou une machine
(serveur ou borne), mutuellement exclusif
Optimisation sur les queryset pour machines et port_related pour
optimiser le temps de chargement avec select_related (vraiment
lent sans)"""
class Meta(PortForm.Meta):
fields = ['room', 'related', 'machine_interface', 'radius', 'vlan_force', 'details']
fields = ['room', 'related', 'machine_interface', 'radius',
'vlan_force', 'details']
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(EditPortForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['machine_interface'].queryset = Interface.objects.all().select_related('domain__extension')
self.fields['related'].queryset = Port.objects.all().select_related('switch__switch_interface__domain__extension').order_by('switch', 'port')
self.fields['machine_interface'].queryset = Interface.objects.all()\
.select_related('domain__extension')
self.fields['related'].queryset = Port.objects.all()\
.select_related('switch__switch_interface__domain__extension')\
.order_by('switch', 'port')
class AddPortForm(ModelForm):
"""Permet d'ajouter un port de switch. Voir EditPortForm pour plus
d'informations"""
class Meta(PortForm.Meta):
fields = ['port', 'room', 'machine_interface', 'related', 'radius', 'vlan_force', 'details']
fields = ['port', 'room', 'machine_interface', 'related',
'radius', 'vlan_force', 'details']
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(AddPortForm, self).__init__(*args, prefix=prefix, **kwargs)
class StackForm(ModelForm):
"""Permet d'edition d'une stack : stack_id, et switches membres
de la stack"""
class Meta:
model = Stack
fields = '__all__'
......@@ -62,7 +95,9 @@ class StackForm(ModelForm):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(StackForm, self).__init__(*args, prefix=prefix, **kwargs)
class EditSwitchForm(ModelForm):
"""Permet d'éditer un switch : nom et nombre de ports"""
class Meta:
model = Switch
fields = '__all__'
......@@ -73,7 +108,10 @@ class EditSwitchForm(ModelForm):
self.fields['location'].label = 'Localisation'
self.fields['number'].label = 'Nombre de ports'
class NewSwitchForm(ModelForm):
"""Permet de créer un switch : emplacement, paramètres machine,
membre d'un stack (option), nombre de ports (number)"""
class Meta(EditSwitchForm.Meta):
fields = ['location', 'number', 'details', 'stack', 'stack_member_id']
......@@ -81,7 +119,9 @@ class NewSwitchForm(ModelForm):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(NewSwitchForm, self).__init__(*args, prefix=prefix, **kwargs)
class EditRoomForm(ModelForm):
"""Permet d'éediter le nom et commentaire d'une prise murale"""
class Meta:
model = Room
fields = '__all__'
......@@ -89,4 +129,3 @@ class EditRoomForm(ModelForm):
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(EditRoomForm, self).__init__(*args, prefix=prefix, **kwargs)
This diff is collapsed.
......@@ -19,6 +19,12 @@
# 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.
"""
Definition des urls de l'application topologie.
Inclu dans urls de re2o.
Fait référence aux fonctions du views
"""
from __future__ import unicode_literals
......@@ -33,18 +39,33 @@ urlpatterns = [
url(r'^new_room/$', views.new_room, name='new-room'),
url(r'^edit_room/(?P<room_id>[0-9]+)$', views.edit_room, name='edit-room'),
url(r'^del_room/(?P<room_id>[0-9]+)$', views.del_room, name='del-room'),
url(r'^switch/(?P<switch_id>[0-9]+)$', views.index_port, name='index-port'),
url(r'^history/(?P<object>switch)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>port)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>room)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^history/(?P<object>stack)/(?P<id>[0-9]+)$', views.history, name='history'),
url(r'^switch/(?P<switch_id>[0-9]+)$',
views.index_port,
name='index-port'),
url(r'^history/(?P<object>switch)/(?P<id>[0-9]+)$',
views.history,
name='history'),
url(r'^history/(?P<object>port)/(?P<id>[0-9]+)$',
views.history,
name='history'),
url(r'^history/(?P<object>room)/(?P<id>[0-9]+)$',
views.history,
name='history'),
url(r'^history/(?P<object>stack)/(?P<id>[0-9]+)$',
views.history,
name='history'),
url(r'^edit_port/(?P<port_id>[0-9]+)$', views.edit_port, name='edit-port'),
url(r'^new_port/(?P<switch_id>[0-9]+)$', views.new_port, name='new-port'),
url(r'^del_port/(?P<port_id>[0-9]+)$', views.del_port, name='del-port'),
url(r'^edit_switch/(?P<switch_id>[0-9]+)$', views.edit_switch, name='edit-switch'),
url(r'^edit_switch/(?P<switch_id>[0-9]+)$',
views.edit_switch,
name='edit-switch'),
url(r'^new_stack/$', views.new_stack, name='new-stack'),
url(r'^index_stack/$', views.index_stack, name='index-stack'),
url(r'^edit_stack/(?P<stack_id>[0-9]+)$', views.edit_stack, name='edit-stack'),
url(r'^del_stack/(?P<stack_id>[0-9]+)$', views.del_stack, name='del-stack'),
url(r'^edit_stack/(?P<stack_id>[0-9]+)$',
views.edit_stack,
name='edit-stack'),
url(r'^del_stack/(?P<stack_id>[0-9]+)$',
views.del_stack,
name='del-stack'),
]
This diff is collapsed.
......@@ -651,10 +651,10 @@ def profil(request, userid):
if not request.user.has_perms(('cableur',)) and users != request.user:
messages.error(request, "Vous ne pouvez pas afficher un autre user que vous sans droit cableur")
return redirect("/users/profil/" + str(request.user.id))
machines = Machine.objects.filter(user__pseudo=users).select_related('user').prefetch_related('interface_set__domain__extension').prefetch_related('interface_set__ipv4__ip_type__extension').prefetch_related('interface_set__type').prefetch_related('interface_set__domain__related_domain__extension')
factures = Facture.objects.filter(user__pseudo=users)
bans = Ban.objects.filter(user__pseudo=users)
whitelists = Whitelist.objects.filter(user__pseudo=users)
machines = Machine.objects.filter(user=users).select_related('user').prefetch_related('interface_set__domain__extension').prefetch_related('interface_set__ipv4__ip_type__extension').prefetch_related('interface_set__type').prefetch_related('interface_set__domain__related_domain__extension')
factures = Facture.objects.filter(user=users)
bans = Ban.objects.filter(user=users)
whitelists = Whitelist.objects.filter(user=users)
list_droits = Right.objects.filter(user=users)
options, created = OptionalUser.objects.get_or_create()
user_solde = options.user_solde
......
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