Commit 48d904b6 authored by Maël Kervella's avatar Maël Kervella

Pep8 compliance on re2o

parent 287ce23d
......@@ -26,6 +26,7 @@
Here are defined some functions to check acl on the application.
"""
def can_view(user):
"""Check if an user can view the application.
......
......@@ -44,12 +44,16 @@ class EditOptionalUserForm(ModelForm):
prefix=prefix,
**kwargs
)
self.fields['is_tel_mandatory'].label = 'Exiger un numéro de\
téléphone'
self.fields['user_solde'].label = 'Activation du solde pour\
les utilisateurs'
self.fields['is_tel_mandatory'].label = (
'Exiger un numéro de téléphone'
)
self.fields['user_solde'].label = (
'Activation du solde pour les utilisateurs'
)
self.fields['max_solde'].label = 'Solde maximum'
self.fields['min_online_payment'].label = 'Montant de rechargement minimum en ligne'
self.fields['min_online_payment'].label = (
'Montant de rechargement minimum en ligne'
)
self.fields['self_adhesion'].label = 'Auto inscription'
......@@ -162,7 +166,6 @@ class EditAssoOptionForm(ModelForm):
return cleaned_data
class EditMailMessageOptionForm(ModelForm):
"""Formulaire d'edition des messages de bienvenue personnalisés"""
class Meta:
......
......@@ -36,6 +36,7 @@ from django.core.cache import cache
from .aes_field import AESEncryptedField
from re2o.mixins import AclMixin
class PreferencesModel(models.Model):
@classmethod
def set_in_cache(cls):
......@@ -46,7 +47,7 @@ class PreferencesModel(models.Model):
@classmethod
def get_cached_value(cls, key):
instance = cache.get(cls().__class__.__name__.lower())
if instance == None:
if instance is None:
instance = cls.set_in_cache()
return getattr(instance, key)
......@@ -146,7 +147,7 @@ class OptionalMachine(AclMixin, PreferencesModel):
@cached_property
def ipv6(self):
return not self.get_cached_value('ipv6_mode') == 'DISABLED'
return not self.get_cached_value('ipv6_mode') == 'DISABLED'
class Meta:
permissions = (
......@@ -230,7 +231,7 @@ class GeneralOption(AclMixin, PreferencesModel):
blank=True,
)
GTU = models.FileField(
upload_to = '',
upload_to='',
default="",
null=True,
blank=True,
......
......@@ -73,7 +73,7 @@ urlpatterns = [
r'^history/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$',
re2o.views.history,
name='history',
kwargs={'application':'preferences'},
kwargs={'application': 'preferences'},
),
url(r'^$', views.display_options, name='display-options'),
]
......@@ -128,7 +128,7 @@ def add_service(request):
messages.success(request, "Ce service a été ajouté")
return redirect(reverse('preferences:display-options'))
return form(
{'preferenceform': service, 'action_name' : 'Ajouter'},
{'preferenceform': service, 'action_name': 'Ajouter'},
'preferences/preferences.html',
request
)
......@@ -151,7 +151,7 @@ def edit_service(request, service_instance, serviceid):
messages.success(request, "Service modifié")
return redirect(reverse('preferences:display-options'))
return form(
{'preferenceform': service, 'action_name' : 'Editer'},
{'preferenceform': service, 'action_name': 'Editer'},
'preferences/preferences.html',
request
)
......@@ -175,7 +175,7 @@ def del_services(request, instances):
suivant %s ne peut être supprimé" % services_del)
return redirect(reverse('preferences:display-options'))
return form(
{'preferenceform': services, 'action_name' : 'Supprimer'},
{'preferenceform': services, 'action_name': 'Supprimer'},
'preferences/preferences.html',
request
)
......@@ -20,4 +20,3 @@
# 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.
#!/usr/bin/env python3
CONTRIBUTORS = ['Gabriel "Chirac" Détraz', 'Maël "MoaMoaK" Kervella', 'Hugo "Klafyvel" Levy--Falk', 'Augustin "Dahlaro" Lemesle', 'Goulven "Lhark" Kermarec', 'Guillaume "Guimoz" Goessel', 'Yoann "Nanoy" Pietri', 'Matthieu "Lebanni" Michelet', 'Arthur "Grizzly" Grisel-Davy', 'Simon "Rezatoune" Brélivet', 'Sellem Lev-Arcady', 'David "5-1" Sinquin', 'Pierre "Redstorm" Cadart', 'Éloi "Goslig" Alain', 'Laouen "Volgarr" Fernet', 'Joanne Steiner', '"Krokmou"', 'Thibault "Tipunchetrhum" de Boutray', 'Baptiste "B" Fournier', 'Daniel "Dstan" Stan', 'Hugo "Shaka" Hervieux', '"Mikachu"', 'Thomas "Nymous" Gaudin', '"Esum"']
CONTRIBUTORS = [
'Gabriel "Chirac" Détraz',
'Maël "MoaMoaK" Kervella',
'Hugo "Klafyvel" Levy--Falk',
'Augustin "Dahlaro" Lemesle',
'Goulven "Lhark" Kermarec',
'Guillaume "Guimoz" Goessel',
'Yoann "Nanoy" Pietri',
'Matthieu "Lebanni" Michelet',
'Arthur "Grizzly" Grisel-Davy',
'Simon "Rezatoune" Brélivet',
'Sellem Lev-Arcady',
'David "5-1" Sinquin',
'Pierre "Redstorm" Cadart',
'Éloi "Goslig" Alain',
'Laouen "Volgarr" Fernet',
'Joanne Steiner',
'"Krokmou"',
'Thibault "Tipunchetrhum" de Boutray',
'Baptiste "B" Fournier',
'Daniel "Dstan" Stan',
'Hugo "Shaka" Hervieux',
'"Mikachu"',
'Thomas "Nymous" Gaudin',
'"Esum"'
]
......@@ -43,13 +43,15 @@ class FieldPermissionModelMixin:
if result is not None:
return result
else:
result = user.has_perm(perm) # Don't supply 'obj', or else infinite recursion.
# Don't supply 'obj', or else infinite recursion.
result = user.has_perm(perm)
if result:
return True
# If no requirement can be met, then permission is denied.
return False
class FieldPermissionModel(FieldPermissionModelMixin, models.Model):
class Meta:
abstract = True
......@@ -76,4 +78,3 @@ class FieldPermissionFormMixin:
class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm):
pass
......@@ -20,18 +20,23 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
Write in a python file the list of all contributors sorted by number of commits.
This list is extracted from the FedeRez gitlab repository.
Write in a python file the list of all contributors sorted by number of
commits. This list is extracted from the current gitlab repository.
"""
from django.core.management.base import BaseCommand, CommandError
import os
class Command(BaseCommand):
help = 'Update contributors list'
help = 'Update contributors list'
def handle(self, *args, **options):
contributeurs = [item.split('\t')[1] for item in os.popen("git shortlog -s -n").read().split("\n") if '\t' in item]
contributeurs = [
item.split('\t')[1]
for item in os.popen("git shortlog -s -n").read().split("\n")
if '\t' in item
]
self.stdout.write(self.style.SUCCESS("Exportation Sucessfull"))
with open("re2o/contributors.py", "w") as contrib_file:
contrib_file.write("#!/usr/bin/env python3\n")
......
......@@ -37,9 +37,15 @@ class RevMixin(object):
class FormRevMixin(object):
def save(self, *args, **kwargs):
if reversion.get_comment() != "" and self.changed_data != []:
reversion.set_comment(reversion.get_comment() + ",%s" % ', '.join(field for field in self.changed_data))
reversion.set_comment(
reversion.get_comment() + ",%s"
% ', '.join(field for field in self.changed_data)
)
elif self.changed_data:
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in self.changed_data))
reversion.set_comment(
"Champs modifié(s) : %s"
% ', '.join(field for field in self.changed_data)
)
return super(FormRevMixin, self).save(*args, **kwargs)
......@@ -47,12 +53,16 @@ class AclMixin(object):
"""This mixin is used in nearly every class/models defined in re2o apps.
It is used by acl, in models (decorators can_...) and in templates tags
:get_instance: Applied on a class, take an id argument, return an instance
:can_create: Applied on a class, take the requested user, return if the user
can do the creation
:can_edit: Applied on an instance, return if the user can edit the instance
:can_delete: Applied on an instance, return if the user can delete the instance
:can_view: Applied on an instance, return if the user can view the instance
:can_view_all: Applied on a class, return if the user can view all instances"""
:can_create: Applied on a class, take the requested user, return if the
user can do the creation
:can_edit: Applied on an instance, return if the user can edit the
instance
:can_delete: Applied on an instance, return if the user can delete the
instance
:can_view: Applied on an instance, return if the user can view the
instance
:can_view_all: Applied on a class, return if the user can view all
instances"""
@classmethod
def get_classname(cls):
......@@ -76,8 +86,12 @@ class AclMixin(object):
un object
:param user_request: instance utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec"""
return user_request.has_perm(cls.get_modulename() + '.add_' + cls.get_classname()), u"Vous n'avez pas le droit\
de créer un " + cls.get_classname()
return (
user_request.has_perm(
cls.get_modulename() + '.add_' + cls.get_classname()
),
u"Vous n'avez pas le droit de créer un " + cls.get_classname()
)
def can_edit(self, user_request, *args, **kwargs):
"""Verifie que l'user a les bons droits pour editer
......@@ -85,7 +99,12 @@ class AclMixin(object):
:param self: Instance à editer
:param user_request: Utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec"""
return user_request.has_perm(self.get_modulename() + '.change_' + self.get_classname()), u"Vous n'avez pas le droit d'éditer des " + self.get_classname()
return (
user_request.has_perm(
self.get_modulename() + '.change_' + self.get_classname()
),
u"Vous n'avez pas le droit d'éditer des " + self.get_classname()
)
def can_delete(self, user_request, *args, **kwargs):
"""Verifie que l'user a les bons droits pour delete
......@@ -93,7 +112,12 @@ class AclMixin(object):
:param self: Instance à delete
:param user_request: Utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec"""
return user_request.has_perm(self.get_modulename() + '.delete_' + self.get_classname()), u"Vous n'avez pas le droit d'éditer des " + self.get_classname()
return (
user_request.has_perm(
self.get_modulename() + '.delete_' + self.get_classname()
),
u"Vous n'avez pas le droit d'éditer des " + self.get_classname()
)
@classmethod
def can_view_all(cls, user_request, *args, **kwargs):
......@@ -101,7 +125,12 @@ class AclMixin(object):
droit particulier view objet correspondant
:param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant"""
return user_request.has_perm(cls.get_modulename() + '.view_' + cls.get_classname()), u"Vous n'avez pas le droit de voir des " + cls.get_classname()
return (
user_request.has_perm(
cls.get_modulename() + '.view_' + cls.get_classname()
),
u"Vous n'avez pas le droit de voir des " + cls.get_classname()
)
def can_view(self, user_request, *args, **kwargs):
"""Vérifie qu'on peut bien voir cette instance particulière avec
......@@ -109,4 +138,9 @@ class AclMixin(object):
:param self: instance à voir
:param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant"""
return user_request.has_perm(self.get_modulename() + '.view_' + self.get_classname()), u"Vous n'avez pas le droit de voir des " + self.get_classname()
return (
user_request.has_perm(
self.get_modulename() + '.view_' + self.get_classname()
),
u"Vous n'avez pas le droit de voir des " + self.get_classname()
)
......@@ -19,15 +19,11 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os, sys, pwd
import os
import sys
import pwd
proj_path="/var/www/re2o"
os.environ.setdefault("DJANGO_SETTINGS_MODULE","re2o.settings")
sys.path.append(proj_path)
os.chdir(proj_path)
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
from django.core.management.base import CommandError
from users.models import User
......@@ -37,14 +33,22 @@ from reversion import revisions as reversion
from django.db import transaction
from getpass import getpass
proj_path = "/var/www/re2o"
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
sys.path.append(proj_path)
os.chdir(proj_path)
application = get_wsgi_application()
def get_user(pseudo):
"""Cherche un utilisateur re2o à partir de son pseudo"""
user = User.objects.filter(pseudo=pseudo)
if len(user)==0:
if len(user) == 0:
raise CommandError("Utilisateur invalide")
if len(user)>1:
raise CommandError("Plusieurs utilisateurs correspondant à ce pseudo. Ceci NE DEVRAIT PAS arriver")
if len(user) > 1:
raise CommandError("Plusieurs utilisateurs correspondant à ce "
"pseudo. Ceci NE DEVRAIT PAS arriver")
return user[0]
......@@ -53,7 +57,7 @@ def get_system_user():
return pwd.getpwuid(int(os.getenv("SUDO_UID") or os.getuid())).pw_name
def form_cli(Form,user,action,*args,**kwargs):
def form_cli(Form, user, action, *args, **kwargs):
"""
Remplit un formulaire à partir de la ligne de commande
Form : le formulaire (sous forme de classe) à remplir
......@@ -61,26 +65,30 @@ def form_cli(Form,user,action,*args,**kwargs):
action : l'action réalisée par le formulaire (pour les logs)
Les arguments suivants sont transmis tels quels au formulaire.
"""
data={}
dumb_form = Form(user=user,*args,**kwargs)
data = {}
dumb_form = Form(user=user, *args, **kwargs)
for key in dumb_form.fields:
if not dumb_form.fields[key].widget.input_type=='hidden':
if dumb_form.fields[key].widget.input_type=='password':
data[key]=getpass("%s : " % dumb_form.fields[key].label)
if not dumb_form.fields[key].widget.input_type == 'hidden':
if dumb_form.fields[key].widget.input_type == 'password':
data[key] = getpass("%s : " % dumb_form.fields[key].label)
else:
data[key]=input("%s : " % dumb_form.fields[key].label)
data[key] = input("%s : " % dumb_form.fields[key].label)
form = Form(data,user=user,*args,**kwargs)
form = Form(data, user=user, *args, **kwargs)
if not form.is_valid():
sys.stderr.write("Erreurs : \n")
for err in form.errors:
#Oui, oui, on gère du HTML là où d'autres ont eu la lumineuse idée de le mettre
sys.stderr.write("\t%s : %s\n" % (err,strip_tags(form.errors[err])))
# Oui, oui, on gère du HTML là où d'autres ont eu la
# lumineuse idée de le mettre
sys.stderr.write(
"\t%s : %s\n" % (err, strip_tags(form.errors[err]))
)
raise CommandError("Formulaire invalide")
with transaction.atomic(), reversion.create_revision():
form.save()
reversion.set_user(user)
reversion.set_comment(action)
form.save()
reversion.set_user(user)
reversion.set_comment(action)
sys.stdout.write("%s : effectué. La modification peut prendre quelques minutes pour s'appliquer.\n" % action)
sys.stdout.write("%s : effectué. La modification peut prendre "
"quelques minutes pour s'appliquer.\n" % action)
......@@ -126,7 +126,7 @@ LANGUAGE_CODE = 'en'
# Proritary location search for translations
# then searches in {app}/locale/ for app in INSTALLED_APPS
LOCALE_PATHS = [
BASE_DIR + '/templates/locale/' # to define translations outside of apps
BASE_DIR + '/templates/locale/' # For translations outside of apps
]
TIME_ZONE = 'Europe/Paris'
......
......@@ -73,23 +73,22 @@ EMAIL_PORT = MY_EMAIL_PORT
# Reglages pour la bdd ldap
LDAP = {
'base_user_dn' : 'cn=Utilisateurs,dc=example,dc=org',
'base_userservice_dn' : 'ou=service-users,dc=example,dc=org',
'base_usergroup_dn' : 'ou=posix,ou=groups,dc=example,dc=org',
'base_userservicegroup_dn' : 'ou=services,ou=groups,dc=example,dc=org',
'user_gid' : 500,
'base_user_dn': 'cn=Utilisateurs,dc=example,dc=org',
'base_userservice_dn': 'ou=service-users,dc=example,dc=org',
'base_usergroup_dn': 'ou=posix,ou=groups,dc=example,dc=org',
'base_userservicegroup_dn': 'ou=services,ou=groups,dc=example,dc=org',
'user_gid': 500,
}
UID_RANGES = {
'users' : [21001,30000],
'service-users' : [20000,21000],
'users': [21001, 30000],
'service-users': [20000, 21000],
}
# Chaque groupe a un gid assigné, voici la place libre pour assignation
GID_RANGES = {
'posix' : [501, 600],
'posix': [501, 600],
}
OPTIONNAL_APPS = ()
......@@ -18,4 +18,3 @@
# 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.
......@@ -85,32 +85,32 @@ register = template.Library()
MODEL_NAME = {
# cotisations
'Facture' : cotisations.models.Facture,
'Vente' : cotisations.models.Vente,
'Article' : cotisations.models.Article,
'Banque' : cotisations.models.Banque,
'Paiement' : cotisations.models.Paiement,
'Cotisation' : cotisations.models.Cotisation,
'Facture': cotisations.models.Facture,
'Vente': cotisations.models.Vente,
'Article': cotisations.models.Article,
'Banque': cotisations.models.Banque,
'Paiement': cotisations.models.Paiement,
'Cotisation': cotisations.models.Cotisation,
# machines
'Machine' : machines.models.Machine,
'MachineType' : machines.models.MachineType,
'IpType' : machines.models.IpType,
'Vlan' : machines.models.Vlan,
'Nas' : machines.models.Nas,
'SOA' : machines.models.SOA,
'Extension' : machines.models.Extension,
'Mx' : machines.models.Mx,
'Ns' : machines.models.Ns,
'Txt' : machines.models.Txt,
'Srv' : machines.models.Srv,
'Interface' : machines.models.Interface,
'Domain' : machines.models.Domain,
'IpList' : machines.models.IpList,
'Ipv6List' : machines.models.Ipv6List,
'machines.Service' : machines.models.Service,
'Service_link' : machines.models.Service_link,
'OuverturePortList' : machines.models.OuverturePortList,
'OuverturePort' : machines.models.OuverturePort,
'Machine': machines.models.Machine,
'MachineType': machines.models.MachineType,
'IpType': machines.models.IpType,
'Vlan': machines.models.Vlan,
'Nas': machines.models.Nas,
'SOA': machines.models.SOA,
'Extension': machines.models.Extension,
'Mx': machines.models.Mx,
'Ns': machines.models.Ns,
'Txt': machines.models.Txt,
'Srv': machines.models.Srv,
'Interface': machines.models.Interface,
'Domain': machines.models.Domain,
'IpList': machines.models.IpList,
'Ipv6List': machines.models.Ipv6List,
'machines.Service': machines.models.Service,
'Service_link': machines.models.Service_link,
'OuverturePortList': machines.models.OuverturePortList,
'OuverturePort': machines.models.OuverturePort,
# preferences
'OptionalUser': preferences.models.OptionalUser,
'OptionalMachine': preferences.models.OptionalMachine,
......@@ -120,25 +120,25 @@ MODEL_NAME = {
'AssoOption': preferences.models.AssoOption,
'MailMessageOption': preferences.models.MailMessageOption,
# topologie
'Stack' : topologie.models.Stack,
'Switch' : topologie.models.Switch,
'AccessPoint' : topologie.models.AccessPoint,
'ModelSwitch' : topologie.models.ModelSwitch,
'ConstructorSwitch' : topologie.models.ConstructorSwitch,
'Port' : topologie.models.Port,
'Room' : topologie.models.Room,
'Building' : topologie.models.Building,
'SwitchBay' : topologie.models.SwitchBay,
'Stack': topologie.models.Stack,
'Switch': topologie.models.Switch,
'AccessPoint': topologie.models.AccessPoint,
'ModelSwitch': topologie.models.ModelSwitch,
'ConstructorSwitch': topologie.models.ConstructorSwitch,
'Port': topologie.models.Port,
'Room': topologie.models.Room,
'Building': topologie.models.Building,
'SwitchBay': topologie.models.SwitchBay,
# users
'User' : users.models.User,
'Adherent' : users.models.Adherent,
'Club' : users.models.Club,
'ServiceUser' : users.models.ServiceUser,
'School' : users.models.School,
'ListRight' : users.models.ListRight,
'ListShell' : users.models.ListShell,
'Ban' : users.models.Ban,
'Whitelist' : users.models.Whitelist,
'User': users.models.User,
'Adherent': users.models.Adherent,
'Club': users.models.Club,
'ServiceUser': users.models.ServiceUser,
'School': users.models.School,
'ListRight': users.models.ListRight,
'ListShell': users.models.ListShell,
'Ban': users.models.Ban,
'Whitelist': users.models.Whitelist,
}
......@@ -184,17 +184,41 @@ def get_callback(tag_name, obj=None):
if tag_name == 'cannot_view_all':
return acl_fct(obj.can_view_all, True)
if tag_name == 'can_view_app':
return acl_fct(lambda x : (not any(not sys.modules[o].can_view(x) for o in obj), None), False)
return acl_fct(
lambda x: (
not any(not sys.modules[o].can_view(x) for o in obj),
None
),
False
)
if tag_name == 'cannot_view_app':
return acl_fct(lambda x : (not any(not sys.modules[o].can_view(x) for o in obj), None), True)
return acl_fct(
lambda x: (
not any(not sys.modules[o].can_view(x) for o in obj),
None
),
True
)
if tag_name == 'can_edit_history':
return acl_fct(lambda user:(user.has_perm('admin.change_logentry'),None),False)
return acl_fct(
lambda user: (user.has_perm('admin.change_logentry'), None),
False
)
if tag_name == 'cannot_edit_history':
return acl_fct(lambda user:(user.has_perm('admin.change_logentry'),None),True)
return acl_fct(
lambda user: (user.has_perm('admin.change_logentry'), None),
True
)
if tag_name == 'can_view_any_app':
return acl_fct(lambda x : (any(sys.modules[o].can_view(x) for o in obj), None), False)
return acl_fct(
lambda x: (any(sys.modules[o].can_view(x) for o in obj), None),
False
)
if tag_name == 'cannot_view_any_app':
return acl_fct(lambda x : (any(sys.modules[o].can_view(x) for o in obj), None), True)
return acl_fct(
lambda x: (any(sys.modules[o].can_view(x) for o in obj), None),
True
)
raise template.TemplateSyntaxError(
"%r tag is not a valid can_xxx tag" % tag_name
......@@ -246,11 +270,11 @@ def acl_app_filter(parser, token):
tag_name, *app_name = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError(
"%r tag require 1 argument : an application"
"%r tag require 1 argument: an application"
% token.contents.split()[0]
)
for name in app_name:
if not name in sys.modules.keys():
if name not in sys.modules.keys():
raise template.TemplateSyntaxError(
"%r is not a registered application for acl."
% name
......@@ -270,6 +294,7 @@ def acl_app_filter(parser, token):
return AclNode(callback, oknodes, konodes)
@register.tag('can_change')
@register.tag('cannot_change')
def acl_change_filter(parser, token):
......@@ -283,7 +308,7 @@ def acl_change_filter(parser, token):
args = tag_content[3:]
except ValueError:
raise template.TemplateSyntaxError(
"%r tag require at least 2 argument : the model and the field"
"%r tag require at least 2 argument: the model and the field"
% token.contents.split()[0]
)
......@@ -306,6 +331,7 @@ def acl_change_filter(parser, token):
return AclNode(callback, oknodes, konodes, *args)
@register.tag('can_create')
@register.tag('cannot_create')
@register.tag('can_edit_all')
......@@ -324,7 +350,7 @@ def acl_model_filter(parser, token):
args = tag_content[2:]
except ValueError:
raise template.TemplateSyntaxError(
"%r tag require at least 1 argument : the model"
"%r tag require at least 1 argument: the model"
% token.contents.split()[0]
)
......@@ -364,7 +390,7 @@ def acl_instance_filter(parser, token):
args = tag_content[2:]
except ValueError:
raise template.TemplateSyntaxError(
"%r tag require at least 1 argument : the instance"
"%r tag require at least 1 argument: the instance"
% token.contents.split()[0]
)
......
......@@ -36,13 +36,14 @@ from bootstrap3.forms import render_field
register = template.Library()
@register.simple_tag
def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
"""
Render a form where some specific fields are rendered using Twitter
Typeahead and/or splitree's Bootstrap Tokenfield to improve the performance, the
speed and UX when dealing with very large datasets (select with 50k+ elts
for instance).
Typeahead and/or splitree's Bootstrap Tokenfield to improve the
performance, the speed and UX when dealing with very large datasets
(select with 50k+ elts for instance).
When the fields specified should normally be rendered as a select with
single selectable option, Twitter Typeahead is used for a better display
and the matching query engine. When dealing with multiple selectable
......@@ -189,8 +190,6 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
return mbf_form.render()
class MBFForm():
""" An object to hold all the information and useful methods needed to
create and render a massive django form into an actual HTML and JS
......@@ -198,7 +197,6 @@ class MBFForm():
Every field that is not listed is rendered as a normal bootstrap_field.
"""
def __init__(self, form, mbf_fields, *args, **kwargs):
# The django form object
self.form = form
......@@ -224,14 +222,13 @@ class MBFForm():
# HTML code to insert inside a template
self.html = ""
def render(self):
""" HTML code for the fully rendered form with all the necessary form
"""
for name, field in self.form.fields.items():
if not name in self.exclude:
if name not in self.exclude:
if name in self.fields and not name in self.hidden_fields:
if name in self.fields and name not in self.hidden_fields:
mbf_field = MBFField(
name,
field,
......@@ -256,9 +253,6 @@ class MBFForm():
return mark_safe(self.html)
class MBFField():
""" An object to hold all the information and useful methods needed to
create and render a massive django form field into an actual HTML and JS
......@@ -270,7 +264,6 @@ class MBFField():
the displayed input. It's used to store the actual data that will be sent
to the server """
def __init__(self, name_, field_, bound_, choices_, engine_, match_func_,
update_on_, gen_select_, *args_, **kwargs_):
......@@ -278,8 +271,8 @@ class MBFField():
if not isinstance(field_.widget, Select):
raise ValueError(
('Field named {f_name} is not a Select and'
'can\'t be rendered with massive_bootstrap_form.'
).format(