From 315560ba5c9c5fc46098c8ad93b88fbd2dfabbe3 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Thu, 26 Oct 2017 05:07:11 +0200 Subject: [PATCH 01/11] =?UTF-8?q?Mod=C3=A8le=20et=20constructeurs=20de=20s?= =?UTF-8?q?witches?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- re2o/utils.py | 9 + topologie/admin.py | 14 +- topologie/forms.py | 24 ++- .../migrations/0032_auto_20171026_0338.py | 36 ++++ topologie/models.py | 28 ++- .../topologie/aff_constructor_switch.html | 54 +++++ .../templates/topologie/aff_model_switch.html | 56 ++++++ topologie/templates/topologie/aff_switch.html | 4 +- .../topologie/index_model_switch.html | 46 +++++ topologie/templates/topologie/sidebar.html | 4 + topologie/urls.py | 34 ++++ topologie/views.py | 187 +++++++++++++++++- 12 files changed, 489 insertions(+), 7 deletions(-) create mode 100644 topologie/migrations/0032_auto_20171026_0338.py create mode 100644 topologie/templates/topologie/aff_constructor_switch.html create mode 100644 topologie/templates/topologie/aff_model_switch.html create mode 100644 topologie/templates/topologie/index_model_switch.html diff --git a/re2o/utils.py b/re2o/utils.py index 739dd200..2560e6c2 100644 --- a/re2o/utils.py +++ b/re2o/utils.py @@ -216,6 +216,15 @@ class SortTable: 'stack_id': ['stack_id'], 'default': ['stack_id'], } + TOPOLOGIE_INDEX_MODEL_SWITCH = { + 'model_switch_name': ['reference'], + 'model_switch__contructor' : ['constructor__name'], + 'default': ['reference'], + } + TOPOLOGIE_INDEX_CONSTRUCTOR_SWITCH = { + 'room_name': ['name'], + 'default': ['name'], + } LOGS_INDEX = { 'sum_date': ['revision__date_created'], 'default': ['-revision__date_created'], diff --git a/topologie/admin.py b/topologie/admin.py index bfc2a393..a4591222 100644 --- a/topologie/admin.py +++ b/topologie/admin.py @@ -29,7 +29,7 @@ from __future__ import unicode_literals from django.contrib import admin from reversion.admin import VersionAdmin -from .models import Port, Room, Switch, Stack +from .models import Port, Room, Switch, Stack, ModelSwitch, ConstructorSwitch class StackAdmin(VersionAdmin): @@ -52,7 +52,19 @@ class RoomAdmin(VersionAdmin): pass +class ModelSwitchAdmin(VersionAdmin): + """Administration d'un modèle de switch""" + pass + + +class ConstructorSwitchAdmin(VersionAdmin): + """Administration d'un constructeur d'un switch""" + pass + + admin.site.register(Port, PortAdmin) admin.site.register(Room, RoomAdmin) admin.site.register(Switch, SwitchAdmin) admin.site.register(Stack, StackAdmin) +admin.site.register(ModelSwitch, ModelSwitchAdmin) +admin.site.register(ConstructorSwitch, ConstructorSwitchAdmin) diff --git a/topologie/forms.py b/topologie/forms.py index c8e39d6a..3ad2e7be 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -34,7 +34,7 @@ from __future__ import unicode_literals from machines.models import Interface from django.forms import ModelForm -from .models import Port, Switch, Room, Stack +from .models import Port, Switch, Room, Stack, ModelSwitch, ConstructorSwitch class PortForm(ModelForm): @@ -136,3 +136,25 @@ class EditRoomForm(ModelForm): def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(EditRoomForm, self).__init__(*args, prefix=prefix, **kwargs) + + +class EditModelSwitchForm(ModelForm): + """Permet d'éediter un modèle de switch : nom et constructeur""" + class Meta: + model = ModelSwitch + fields = '__all__' + + def __init__(self, *args, **kwargs): + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(EditModelSwitchForm, self).__init__(*args, prefix=prefix, **kwargs) + + +class EditConstructorSwitchForm(ModelForm): + """Permet d'éediter le nom d'un constructeur""" + class Meta: + model = ConstructorSwitch + fields = '__all__' + + def __init__(self, *args, **kwargs): + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(EditConstructorSwitchForm, self).__init__(*args, prefix=prefix, **kwargs) diff --git a/topologie/migrations/0032_auto_20171026_0338.py b/topologie/migrations/0032_auto_20171026_0338.py new file mode 100644 index 00000000..37548306 --- /dev/null +++ b/topologie/migrations/0032_auto_20171026_0338.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-10-26 01:38 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('topologie', '0031_auto_20171015_2033'), + ] + + operations = [ + migrations.CreateModel( + name='ConstructorSwitch', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name='ModelSwitch', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('reference', models.CharField(max_length=255)), + ('constructor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='topologie.ConstructorSwitch')), + ], + ), + migrations.AddField( + model_name='switch', + name='model', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='topologie.ModelSwitch'), + ), + ] diff --git a/topologie/models.py b/topologie/models.py index adcc7a57..0f277434 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -93,12 +93,18 @@ class Switch(models.Model): number = models.PositiveIntegerField() details = models.CharField(max_length=255, blank=True) stack = models.ForeignKey( - Stack, + 'topologie.Stack', blank=True, null=True, on_delete=models.SET_NULL ) stack_member_id = models.PositiveIntegerField(blank=True, null=True) + model = models.ForeignKey( + 'topologie.ModelSwitch', + blank=True, + null=True, + on_delete=models.SET_NULL + ) class Meta: unique_together = ('stack', 'stack_member_id') @@ -121,6 +127,26 @@ class Switch(models.Model): ne peut être nul"}) +class ModelSwitch(models.Model): + """Un modèle (au sens constructeur) de switch""" + reference = models.CharField(max_length=255) + constructor = models.ForeignKey( + 'topologie.ConstructorSwitch', + on_delete=models.PROTECT + ) + + def __str__(self): + return str(self.constructor) + ' ' + str(self.reference) + + +class ConstructorSwitch(models.Model): + """Un constructeur de switch""" + name = models.CharField(max_length=255) + + def __str__(self): + return str(self.name) + + class Port(models.Model): """ Definition d'un port. Relié à un switch(foreign_key), un port peut etre relié de manière exclusive à : diff --git a/topologie/templates/topologie/aff_constructor_switch.html b/topologie/templates/topologie/aff_constructor_switch.html new file mode 100644 index 00000000..02002f6c --- /dev/null +++ b/topologie/templates/topologie/aff_constructor_switch.html @@ -0,0 +1,54 @@ +{% 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 constructor_switch_list.paginator %} +{% include "pagination.html" with list=constructor_switch_list %} +{% endif %} + + + + + + + + + {% for constructor_switch in constructor_switch_list %} + + + + + {% endfor %} +
{% include "buttons/sort.html" with prefix='constructor-switch' col='name' text='Constructeur' %}
{{constructor_switch}} + + + + {% if is_infra %} + + + + + + + {% endif %} +
diff --git a/topologie/templates/topologie/aff_model_switch.html b/topologie/templates/topologie/aff_model_switch.html new file mode 100644 index 00000000..2e84fb69 --- /dev/null +++ b/topologie/templates/topologie/aff_model_switch.html @@ -0,0 +1,56 @@ +{% 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 model_switch_list.paginator %} +{% include "pagination.html" with list=model_switch_list %} +{% endif %} + + + + + + + + + + {% for model_switch in model_switch_list %} + + + + + + {% endfor %} +
{% include "buttons/sort.html" with prefix='model-switch' col='reference' text='Référence' %}{% include "buttons/sort.html" with prefix='model-switch' col='constructor' text='Constructeur' %}
{{model_switch.reference}}{{model_switch.constructor}} + + + + {% if is_infra %} + + + + + + + {% endif %} +
diff --git a/topologie/templates/topologie/aff_switch.html b/topologie/templates/topologie/aff_switch.html index c0d6c55f..eb326421 100644 --- a/topologie/templates/topologie/aff_switch.html +++ b/topologie/templates/topologie/aff_switch.html @@ -30,7 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc., {% include "buttons/sort.html" with prefix='switch' col='loc' text='Localisation' %} {% include "buttons/sort.html" with prefix='switch' col='ports' text='Ports' %} {% include "buttons/sort.html" with prefix='switch' col='stack' text='Stack' %} - Id interne stack + Id stack + Modèle Détails @@ -47,6 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {{switch.number}} {{switch.stack.name}} {{switch.stack_member_id}} + {{switch.model}} {{switch.details}} {% include 'buttons/history.html' with href='topologie:history' name='switch' id=switch.pk%} diff --git a/topologie/templates/topologie/index_model_switch.html b/topologie/templates/topologie/index_model_switch.html new file mode 100644 index 00000000..784b5ea6 --- /dev/null +++ b/topologie/templates/topologie/index_model_switch.html @@ -0,0 +1,46 @@ +{% extends "topologie/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 %}Modèles de switches{% endblock %} + +{% block content %} +

Modèles de switches

+{% if is_infra %} + Ajouter un modèle +
+{% endif %} +{% include "topologie/aff_model_switch.html" with model_switch_list=model_switch_list %} +

Constructeurs de switches

+{% if is_infra %} + Ajouter un constructeur +
+{% endif %} +{% include "topologie/aff_constructor_switch.html" with constructor_switch_list=constructor_switch_list %} +
+
+
+{% endblock %} diff --git a/topologie/templates/topologie/sidebar.html b/topologie/templates/topologie/sidebar.html index 833af2e3..a2d42896 100644 --- a/topologie/templates/topologie/sidebar.html +++ b/topologie/templates/topologie/sidebar.html @@ -37,4 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc., Stacks + + + Modèles switches et constructeurs + {% endblock %} diff --git a/topologie/urls.py b/topologie/urls.py index 77a78b97..4175c68c 100644 --- a/topologie/urls.py +++ b/topologie/urls.py @@ -54,6 +54,12 @@ urlpatterns = [ url(r'^history/(?Pstack)/(?P[0-9]+)$', views.history, name='history'), + url(r'^history/(?Pmodel_switch)/(?P[0-9]+)$', + views.history, + name='history'), + url(r'^history/(?Pconstructor_switch)/(?P[0-9]+)$', + views.history, + name='history'), url(r'^edit_port/(?P[0-9]+)$', views.edit_port, name='edit-port'), url(r'^new_port/(?P[0-9]+)$', views.new_port, name='new-port'), url(r'^del_port/(?P[0-9]+)$', views.del_port, name='del-port'), @@ -68,4 +74,32 @@ urlpatterns = [ url(r'^del_stack/(?P[0-9]+)$', views.del_stack, name='del-stack'), + url(r'^index_model_switch/$', + views.index_model_switch, + name='index-model-switch' + ), + url(r'^index_model_switch/$', + views.index_model_switch, + name='index-model-switch' + ), + url(r'^new_model_switch/$', + views.new_model_switch, + name='new-model-switch' + ), + url(r'^edit_model_switch/(?P[0-9]+)$', + views.edit_model_switch, + name='edit-model-switch'), + url(r'^del_model_switch/(?P[0-9]+)$', + views.del_model_switch, + name='del-model-switch'), + url(r'^new_constructor_switch/$', + views.new_constructor_switch, + name='new-constructor-switch' + ), + url(r'^edit_constructor_switch/(?P[0-9]+)$', + views.edit_constructor_switch, + name='edit-constructor-switch'), + url(r'^del_constructor_switch/(?P[0-9]+)$', + views.del_constructor_switch, + name='del-constructor-switch'), ] diff --git a/topologie/views.py b/topologie/views.py index dec681b6..5cd413f7 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -45,12 +45,31 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from reversion import revisions as reversion from reversion.models import Version -from topologie.models import Switch, Port, Room, Stack +from topologie.models import ( + Switch, + Port, + Room, + Stack, + ModelSwitch, + ConstructorSwitch +) from topologie.forms import EditPortForm, NewSwitchForm, EditSwitchForm -from topologie.forms import AddPortForm, EditRoomForm, StackForm +from topologie.forms import ( + AddPortForm, + EditRoomForm, + StackForm, + EditModelSwitchForm, + EditConstructorSwitchForm +) from users.views import form from re2o.utils import SortTable -from machines.forms import DomainForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm +from machines.forms import ( + DomainForm, + NewMachineForm, + EditMachineForm, + EditInterfaceForm, + AddInterfaceForm +) from machines.views import generate_ipv4_mbf_param from preferences.models import AssoOption, GeneralOption @@ -103,6 +122,18 @@ def history(request, object_name, object_id): except Room.DoesNotExist: messages.error(request, "Stack inexistante") return redirect("/topologie/") + elif object_name == 'model_switch': + try: + object_instance = ModelSwitch.objects.get(pk=object_id) + except ModelSwitch.DoesNotExist: + messages.error(request, "SwitchModel inexistant") + return redirect("/topologie/") + elif object_name == 'constructor_switch': + try: + object_instance = ConstructorSwitch.objects.get(pk=object_id) + except ConstructorSwitch.DoesNotExist: + messages.error(request, "SwitchConstructor inexistant") + return redirect("/topologie/") else: messages.error(request, "Objet inconnu") return redirect("/topologie/") @@ -198,6 +229,30 @@ def index_stack(request): }) +@login_required +@permission_required('cableur') +def index_model_switch(request): + """ Affichage de l'ensemble des modèles de switches""" + model_switch_list = ModelSwitch.objects + constructor_switch_list = ConstructorSwitch.objects + model_switch_list = SortTable.sort( + model_switch_list, + request.GET.get('col'), + request.GET.get('order'), + SortTable.TOPOLOGIE_INDEX_MODEL_SWITCH + ) + constructor_switch_list = SortTable.sort( + constructor_switch_list, + request.GET.get('col'), + request.GET.get('order'), + SortTable.TOPOLOGIE_INDEX_CONSTRUCTOR_SWITCH + ) + return render(request, 'topologie/index_model_switch.html', { + 'model_switch_list': model_switch_list, + 'constructor_switch_list': constructor_switch_list, + }) + + @login_required @permission_required('infra') def new_port(request, switch_id): @@ -538,3 +593,129 @@ def del_room(request, room_id): 'objet': room, 'objet_name': 'Chambre' }, 'topologie/delete.html', request) + + +@login_required +@permission_required('infra') +def new_model_switch(request): + """Nouveau modèle de switch""" + model_switch = EditModelSwitchForm(request.POST or None) + if model_switch.is_valid(): + with transaction.atomic(), reversion.create_revision(): + model_switch.save() + reversion.set_user(request.user) + reversion.set_comment("Création") + messages.success(request, "Le modèle a été créé") + return redirect("/topologie/index_model_switch/") + return form({'topoform': model_switch}, 'topologie/topo.html', request) + + +@login_required +@permission_required('infra') +def edit_model_switch(request, model_switch_id): + """ Edition d'un modèle de switch""" + try: + model_switch = ModelSwitch.objects.get(pk=model_switch_id) + except ModelSwitch.DoesNotExist: + messages.error(request, u"Modèle inconnu") + return redirect("/topologie/index_model_switch/") + model_switch = EditModelSwitchForm(request.POST or None, instance=model_switch) + if model_switch.is_valid(): + with transaction.atomic(), reversion.create_revision(): + model_switch.save() + reversion.set_user(request.user) + reversion.set_comment("Champs modifié(s) : %s" % ', '.join( + field for field in model_switch.changed_data) + ) + messages.success(request, "Le modèle a bien été modifié") + return redirect("/topologie/index_model_switch/") + return form({'topoform': model_switch}, 'topologie/topo.html', request) + + +@login_required +@permission_required('infra') +def del_model_switch(request, model_switch_id): + """ Suppression d'un modèle de switch""" + try: + model_switch = ModelSwitch.objects.get(pk=model_switch_id) + except ModelSwitch.DoesNotExist: + messages.error(request, u"Modèle inexistant") + return redirect("/topologie/index_model_switch/") + if request.method == "POST": + try: + with transaction.atomic(), reversion.create_revision(): + model_switch.delete() + reversion.set_user(request.user) + reversion.set_comment("Destruction") + messages.success(request, "Le modèle a été détruit") + except ProtectedError: + messages.error(request, "Le modèle %s est affectée à un autre objet,\ + impossible de la supprimer (switch ou user)" % model_switch) + return redirect("/topologie/index_model_switch/") + return form({ + 'objet': model_switch, + 'objet_name': 'Modèle de switch' + }, 'topologie/delete.html', request) + + +@login_required +@permission_required('infra') +def new_constructor_switch(request): + """Nouveau constructeur de switch""" + constructor_switch = EditConstructorSwitchForm(request.POST or None) + if constructor_switch.is_valid(): + with transaction.atomic(), reversion.create_revision(): + constructor_switch.save() + reversion.set_user(request.user) + reversion.set_comment("Création") + messages.success(request, "Le constructeur a été créé") + return redirect("/topologie/index_model_switch/") + return form({'topoform': constructor_switch}, 'topologie/topo.html', request) + + +@login_required +@permission_required('infra') +def edit_constructor_switch(request, constructor_switch_id): + """ Edition d'un constructeur de switch""" + try: + constructor_switch = ConstructorSwitch.objects.get(pk=constructor_switch_id) + except ConstructorSwitch.DoesNotExist: + messages.error(request, u"Constructeur inconnu") + return redirect("/topologie/index_model_switch/") + constructor_switch = EditConstructorSwitchForm(request.POST or None, instance=constructor_switch) + if constructor_switch.is_valid(): + with transaction.atomic(), reversion.create_revision(): + constructor_switch.save() + reversion.set_user(request.user) + reversion.set_comment("Champs modifié(s) : %s" % ', '.join( + field for field in constructor_switch.changed_data) + ) + messages.success(request, "Le modèle a bien été modifié") + return redirect("/topologie/index_model_switch/") + return form({'topoform': constructor_switch}, 'topologie/topo.html', request) + + +@login_required +@permission_required('infra') +def del_constructor_switch(request, constructor_switch_id): + """ Suppression d'un constructeur de switch""" + try: + constructor_switch = ConstructorSwitch.objects.get(pk=constructor_switch_id) + except ConstructorSwitch.DoesNotExist: + messages.error(request, u"Constructeur inexistant") + return redirect("/topologie/index_model_switch/") + if request.method == "POST": + try: + with transaction.atomic(), reversion.create_revision(): + constructor_switch.delete() + reversion.set_user(request.user) + reversion.set_comment("Destruction") + messages.success(request, "Le constructeur a été détruit") + except ProtectedError: + messages.error(request, "Le constructeur %s est affecté à un autre objet,\ + impossible de la supprimer (switch ou user)" % constructor_switch) + return redirect("/topologie/index_model_switch/") + return form({ + 'objet': constructor_switch, + 'objet_name': 'Constructeur de switch' + }, 'topologie/delete.html', request) From 7bc0f2b7035cfa3dda6158aaf8fba907c441f050 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 10:41:48 +0200 Subject: [PATCH 02/11] =?UTF-8?q?Ajoute=20la=20possibilit=C3=A9=20de=20cr?= =?UTF-8?q?=C3=A9er=20une=20s=C3=A9rie=20de=20ports=20pour=20un=20switch.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/forms.py | 12 +++- topologie/models.py | 1 - topologie/templates/topologie/aff_switch.html | 1 + topologie/urls.py | 1 + topologie/views.py | 55 +++++++++++++++++++ 5 files changed, 68 insertions(+), 2 deletions(-) diff --git a/topologie/forms.py b/topologie/forms.py index c8e39d6a..958c6008 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -33,7 +33,8 @@ NewSwitchForm) from __future__ import unicode_literals from machines.models import Interface -from django.forms import ModelForm +from django import forms +from django.forms import ModelForm, Form from .models import Port, Switch, Room, Stack @@ -136,3 +137,12 @@ class EditRoomForm(ModelForm): def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(EditRoomForm, self).__init__(*args, prefix=prefix, **kwargs) + + +class CreatePortsForm(Form): + """Permet de créer une liste de ports pour un switch.""" + begin = forms.IntegerField(label="Début :", min_value=0) + end = forms.IntegerField(label="Fin :", min_value=0) + + + diff --git a/topologie/models.py b/topologie/models.py index adcc7a57..924002b3 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -120,7 +120,6 @@ class Switch(models.Model): raise ValidationError({'stack_member_id': "L'id dans la stack\ ne peut être nul"}) - class Port(models.Model): """ Definition d'un port. Relié à un switch(foreign_key), un port peut etre relié de manière exclusive à : diff --git a/topologie/templates/topologie/aff_switch.html b/topologie/templates/topologie/aff_switch.html index c0d6c55f..b533edec 100644 --- a/topologie/templates/topologie/aff_switch.html +++ b/topologie/templates/topologie/aff_switch.html @@ -53,6 +53,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if is_infra %} {% include 'buttons/edit.html' with href='topologie:edit-switch' id=switch.pk %} {% include 'buttons/suppr.html' with href='machines:del-interface' id=switch.switch_interface.id %} + {% include 'buttons/add.html' with href='topologie:create-ports' id=switch.pk desc='Création de ports'%} {% endif %} diff --git a/topologie/urls.py b/topologie/urls.py index 77a78b97..4b39d5c5 100644 --- a/topologie/urls.py +++ b/topologie/urls.py @@ -35,6 +35,7 @@ from . import views urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^new_switch/$', views.new_switch, name='new-switch'), + url(r'^create_ports/(?P[0-9]+)$', views.create_ports, name='create-ports'), url(r'^index_room/$', views.index_room, name='index-room'), url(r'^new_room/$', views.new_room, name='new-room'), url(r'^edit_room/(?P[0-9]+)$', views.edit_room, name='edit-room'), diff --git a/topologie/views.py b/topologie/views.py index dec681b6..35e62ce3 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -35,6 +35,8 @@ coté models et forms de topologie """ from __future__ import unicode_literals +import itertools + from django.shortcuts import render, redirect from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required @@ -48,6 +50,7 @@ from reversion.models import Version from topologie.models import Switch, Port, Room, Stack from topologie.forms import EditPortForm, NewSwitchForm, EditSwitchForm from topologie.forms import AddPortForm, EditRoomForm, StackForm +from topologie.forms import CreatePortsForm from users.views import form from re2o.utils import SortTable from machines.forms import DomainForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm @@ -409,6 +412,58 @@ def new_switch(request): 'i_mbf_param': i_mbf_param }, 'topologie/switch.html', request) +@login_required +@permission_required('infra') +def create_ports(request, switch_id): + """ Création d'une liste de ports pour un switch.""" + try: + switch = Switch.objects.get(pk=switch_id) + except Switch.DoesNotExist: + messages.error(request, u"Switch inexistant") + return redirect("/topologie/") + + ports = switch.ports.order_by('port') + s_begin = s_end = 0 + if len(ports) > 0: + s_begin = ports[0].port + s_end = ports[len(ports)-1].port + + port_form = CreatePortsForm( + request.POST or None, + initial={'begin':s_begin,'end':s_end} + ) + if port_form.is_valid(): + begin = port_form.cleaned_data['begin'] + end = port_form.cleaned_data['end'] + b = [] + e = [] + if end < begin: + messages.error(request, "Port de fin inférieur au port de début !") + return redirect("/topologie/") + if end - begin > switch.number: + messages.error(request, "Ce switch ne peut avoir autant de ports.") + return redirect("/topologie/") + + if begin < s_begin: + b = range(begin, s_begin) + if end > s_end: + e = range(s_end+1, end+1) + for i in itertools.chain(b,e): + p = Port() + p.switch = switch + p.port = i + try: + with transaction.atomic(), reversion.create_revision(): + p.save() + reversion.set_user(request.user) + reversion.set_comment("Création") + messages.success(request, "Création du port %d" % i) + except IntegrityError: + messages.error(request, "Création d'un port existant.") + return redirect("/topologie/") + + return form({'topoform': port_form,}, 'topologie/switch.html', request) + @login_required @permission_required('infra') From 9c1833ed8f3aa018612bcb76d156a222694a4969 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 11:05:27 +0200 Subject: [PATCH 03/11] =?UTF-8?q?Optimisation=20des=20requ=C3=AAtes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/views.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/topologie/views.py b/topologie/views.py index 35e62ce3..023ed254 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -422,11 +422,12 @@ def create_ports(request, switch_id): messages.error(request, u"Switch inexistant") return redirect("/topologie/") - ports = switch.ports.order_by('port') s_begin = s_end = 0 - if len(ports) > 0: + nb_ports = switch.ports.count() + if nb_ports > 0: + ports = switch.ports.order_by('port') s_begin = ports[0].port - s_end = ports[len(ports)-1].port + s_end = ports.last().port port_form = CreatePortsForm( request.POST or None, From d1e34d795d464765823ba583daf659af958e26f3 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 11:08:54 +0200 Subject: [PATCH 04/11] typo --- topologie/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/topologie/views.py b/topologie/views.py index 023ed254..11b889fa 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -270,7 +270,7 @@ def del_port(request, port_id): port.delete() reversion.set_user(request.user) reversion.set_comment("Destruction") - messages.success(request, "Le port a eté détruit") + messages.success(request, "Le port a été détruit") except ProtectedError: messages.error(request, "Le port %s est affecté à un autre objet,\ impossible de le supprimer" % port) From e3bd4e7ce32637e9451bbc9dbac9473cd1b6e8a9 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 11:14:16 +0200 Subject: [PATCH 05/11] =?UTF-8?q?Int=C3=A9gration=20=C3=A0=20la=20page=20/?= =?UTF-8?q?topologie/switch/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/templates/topologie/index_p.html | 1 + topologie/views.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/topologie/templates/topologie/index_p.html b/topologie/templates/topologie/index_p.html index 84159659..3f9356f2 100644 --- a/topologie/templates/topologie/index_p.html +++ b/topologie/templates/topologie/index_p.html @@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% if is_infra %} Editer Ajouter un port + Ajouter des ports {% endif %} {% include "topologie/aff_port.html" with port_list=port_list %}
diff --git a/topologie/views.py b/topologie/views.py index 11b889fa..4561506a 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -440,10 +440,10 @@ def create_ports(request, switch_id): e = [] if end < begin: messages.error(request, "Port de fin inférieur au port de début !") - return redirect("/topologie/") + return redirect("/topologie/switch/" + str(switch.id)) if end - begin > switch.number: messages.error(request, "Ce switch ne peut avoir autant de ports.") - return redirect("/topologie/") + return redirect("/topologie/switch/" + str(switch.id)) if begin < s_begin: b = range(begin, s_begin) @@ -461,7 +461,7 @@ def create_ports(request, switch_id): messages.success(request, "Création du port %d" % i) except IntegrityError: messages.error(request, "Création d'un port existant.") - return redirect("/topologie/") + return redirect("/topologie/switch/" + str(switch.id)) return form({'topoform': port_form,}, 'topologie/switch.html', request) From 1c8a3a87c0ac77701a1048d94b161efdfe986bd5 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 11:29:44 +0200 Subject: [PATCH 06/11] =?UTF-8?q?Suppression=20de=20v=C3=A9rifications=20i?= =?UTF-8?q?nutiles.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/views.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/topologie/views.py b/topologie/views.py index 4561506a..dcfce4d9 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -445,10 +445,8 @@ def create_ports(request, switch_id): messages.error(request, "Ce switch ne peut avoir autant de ports.") return redirect("/topologie/switch/" + str(switch.id)) - if begin < s_begin: - b = range(begin, s_begin) - if end > s_end: - e = range(s_end+1, end+1) + b = range(begin, s_begin) + e = range(s_end+1, end+1) for i in itertools.chain(b,e): p = Port() p.switch = switch From da85cd9254f64e688ce62c3ebda363ff1ca0f0a8 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 11:51:41 +0200 Subject: [PATCH 07/11] =?UTF-8?q?Moins=20de=20requ=C3=AAtes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/topologie/views.py b/topologie/views.py index dcfce4d9..bad4d246 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -425,9 +425,9 @@ def create_ports(request, switch_id): s_begin = s_end = 0 nb_ports = switch.ports.count() if nb_ports > 0: - ports = switch.ports.order_by('port') - s_begin = ports[0].port - s_end = ports.last().port + ports = switch.ports.order_by('port').values('port') + s_begin = ports.first().get('port') + s_end = ports.last().get('port') port_form = CreatePortsForm( request.POST or None, From a2e03538e367a7b440c9623c342a438d94c6750a Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Thu, 26 Oct 2017 18:48:09 +0200 Subject: [PATCH 08/11] Gentil paginateur --- topologie/templates/topologie/aff_switch.html | 4 ++++ topologie/templates/topologie/index.html | 1 + topologie/views.py | 12 ++++++++++++ 3 files changed, 17 insertions(+) diff --git a/topologie/templates/topologie/aff_switch.html b/topologie/templates/topologie/aff_switch.html index eb326421..6542ce13 100644 --- a/topologie/templates/topologie/aff_switch.html +++ b/topologie/templates/topologie/aff_switch.html @@ -22,6 +22,10 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. {% endcomment %} +{% if switch_list.paginator %} +{% include "pagination.html" with list=switch_list %} +{% endif %} + diff --git a/topologie/templates/topologie/index.html b/topologie/templates/topologie/index.html index 72b522d0..6b17b6de 100644 --- a/topologie/templates/topologie/index.html +++ b/topologie/templates/topologie/index.html @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,

Switchs

{% if is_infra %} Ajouter un switch +
{% endif %} {% include "topologie/aff_switch.html" with switch_list=switch_list %}
diff --git a/topologie/views.py b/topologie/views.py index 5cd413f7..d72be310 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -89,6 +89,18 @@ def index(request): request.GET.get('order'), SortTable.TOPOLOGIE_INDEX ) + options, _created = GeneralOption.objects.get_or_create() + pagination_number = options.pagination_number + paginator = Paginator(switch_list, pagination_number) + page = request.GET.get('page') + try: + switch_list = paginator.page(page) + except PageNotAnInteger: + # If page is not an integer, deliver first page. + switch_list = paginator.page(1) + except EmptyPage: + # If page is out of range (e.g. 9999), deliver last page of results. + switch_list = paginator.page(paginator.num_pages) return render(request, 'topologie/index.html', { 'switch_list': switch_list }) From 5471169827aa2c98c31b3deda69b6c3f4ec1dc60 Mon Sep 17 00:00:00 2001 From: Gabriel Detraz Date: Thu, 26 Oct 2017 18:54:38 +0200 Subject: [PATCH 09/11] Formatage et nettoyage du formulaire switch --- topologie/forms.py | 3 ++- topologie/templates/topologie/switch.html | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/topologie/forms.py b/topologie/forms.py index 3ad2e7be..a325c0f9 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -125,7 +125,8 @@ class NewSwitchForm(ModelForm): def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) super(NewSwitchForm, self).__init__(*args, prefix=prefix, **kwargs) - + self.fields['location'].label = 'Localisation' + self.fields['number'].label = 'Nombre de ports' class EditRoomForm(ModelForm): """Permet d'éediter le nom et commentaire d'une prise murale""" diff --git a/topologie/templates/topologie/switch.html b/topologie/templates/topologie/switch.html index e87570c4..1753161e 100644 --- a/topologie/templates/topologie/switch.html +++ b/topologie/templates/topologie/switch.html @@ -47,12 +47,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% csrf_token %} {% if topoform %} +

Réglage spécifiques du switch

{% massive_bootstrap_form topoform 'switch_interface' %} {% endif %} {% if machineform %} +

Réglages généraux de la machine associée au switch

{% massive_bootstrap_form machineform 'user' %} {% endif %} {% if interfaceform %} +

Réglages généraux de l'interface associée au switch

{% if i_mbf_param %} {% massive_bootstrap_form interfaceform 'ipv4,machine' mbf_param=i_mbf_param %} {% else %} @@ -60,6 +63,7 @@ with this program; if not, write to the Free Software Foundation, Inc., {% endif %} {% endif %} {% if domainform %} +

Nom de la machine

{% bootstrap_form domainform %} {% endif %} {% bootstrap_button "Créer ou modifier" button_type="submit" icon="ok" %} From 4b2edd542e49f7c11dd34cabd994f2ae33997b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Kervella?= Date: Thu, 26 Oct 2017 19:29:34 +0000 Subject: [PATCH 10/11] Pep8 et pylint compliance --- topologie/forms.py | 3 --- topologie/models.py | 1 + topologie/urls.py | 4 +++- topologie/views.py | 39 +++++++++++++++++++++++---------------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/topologie/forms.py b/topologie/forms.py index 958c6008..a25419af 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -143,6 +143,3 @@ class CreatePortsForm(Form): """Permet de créer une liste de ports pour un switch.""" begin = forms.IntegerField(label="Début :", min_value=0) end = forms.IntegerField(label="Fin :", min_value=0) - - - diff --git a/topologie/models.py b/topologie/models.py index 924002b3..adcc7a57 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -120,6 +120,7 @@ class Switch(models.Model): raise ValidationError({'stack_member_id': "L'id dans la stack\ ne peut être nul"}) + class Port(models.Model): """ Definition d'un port. Relié à un switch(foreign_key), un port peut etre relié de manière exclusive à : diff --git a/topologie/urls.py b/topologie/urls.py index 4b39d5c5..de7186a8 100644 --- a/topologie/urls.py +++ b/topologie/urls.py @@ -35,7 +35,9 @@ from . import views urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^new_switch/$', views.new_switch, name='new-switch'), - url(r'^create_ports/(?P[0-9]+)$', views.create_ports, name='create-ports'), + url(r'^create_ports/(?P[0-9]+)$', + views.create_ports, + name='create-ports'), url(r'^index_room/$', views.index_room, name='index-room'), url(r'^new_room/$', views.new_room, name='new-room'), url(r'^edit_room/(?P[0-9]+)$', views.edit_room, name='edit-room'), diff --git a/topologie/views.py b/topologie/views.py index bad4d246..80b831f7 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -53,7 +53,13 @@ from topologie.forms import AddPortForm, EditRoomForm, StackForm from topologie.forms import CreatePortsForm from users.views import form from re2o.utils import SortTable -from machines.forms import DomainForm, NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm +from machines.forms import ( + DomainForm, + NewMachineForm, + EditMachineForm, + EditInterfaceForm, + AddInterfaceForm +) from machines.views import generate_ipv4_mbf_param from preferences.models import AssoOption, GeneralOption @@ -141,7 +147,9 @@ def index_port(request, switch_id): .select_related('room')\ .select_related('machine_interface__domain__extension')\ .select_related('machine_interface__machine__user')\ - .select_related('related__switch__switch_interface__domain__extension')\ + .select_related( + 'related__switch__switch_interface__domain__extension' + )\ .select_related('switch') port_list = SortTable.sort( port_list, @@ -403,7 +411,7 @@ def new_switch(request): reversion.set_comment("Création") messages.success(request, "Le switch a été créé") return redirect("/topologie/") - i_mbf_param = generate_ipv4_mbf_param( interface, False ) + i_mbf_param = generate_ipv4_mbf_param(interface, False) return form({ 'topoform': switch, 'machineform': machine, @@ -412,6 +420,7 @@ def new_switch(request): 'i_mbf_param': i_mbf_param }, 'topologie/switch.html', request) + @login_required @permission_required('infra') def create_ports(request, switch_id): @@ -431,13 +440,11 @@ def create_ports(request, switch_id): port_form = CreatePortsForm( request.POST or None, - initial={'begin':s_begin,'end':s_end} + initial={'begin': s_begin, 'end': s_end} ) if port_form.is_valid(): begin = port_form.cleaned_data['begin'] end = port_form.cleaned_data['end'] - b = [] - e = [] if end < begin: messages.error(request, "Port de fin inférieur au port de début !") return redirect("/topologie/switch/" + str(switch.id)) @@ -445,15 +452,15 @@ def create_ports(request, switch_id): messages.error(request, "Ce switch ne peut avoir autant de ports.") return redirect("/topologie/switch/" + str(switch.id)) - b = range(begin, s_begin) - e = range(s_end+1, end+1) - for i in itertools.chain(b,e): - p = Port() - p.switch = switch - p.port = i + begin_range = range(begin, s_begin) + end_range = range(s_end+1, end+1) + for i in itertools.chain(begin_range, end_range): + port = Port() + port.switch = switch + port.port = i try: with transaction.atomic(), reversion.create_revision(): - p.save() + port.save() reversion.set_user(request.user) reversion.set_comment("Création") messages.success(request, "Création du port %d" % i) @@ -461,8 +468,8 @@ def create_ports(request, switch_id): messages.error(request, "Création d'un port existant.") return redirect("/topologie/switch/" + str(switch.id)) - return form({'topoform': port_form,}, 'topologie/switch.html', request) - + return form({'topoform': port_form}, 'topologie/switch.html', request) + @login_required @permission_required('infra') @@ -521,7 +528,7 @@ def edit_switch(request, switch_id): ) messages.success(request, "Le switch a bien été modifié") return redirect("/topologie/") - i_mbf_param = generate_ipv4_mbf_param( interface_form, False ) + i_mbf_param = generate_ipv4_mbf_param(interface_form, False) return form({ 'topoform': switch_form, 'machineform': machine_form, From 3ace31e24eec1b49dfc71c98714651382dc95059 Mon Sep 17 00:00:00 2001 From: LEVY-FALK Hugo Date: Thu, 26 Oct 2017 23:29:26 +0200 Subject: [PATCH 11/11] =?UTF-8?q?Passage=20de=20la=20logique=20dans=20le?= =?UTF-8?q?=20mod=C3=A8le.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- topologie/forms.py | 2 +- topologie/models.py | 31 +++++++++++++++++++++++++++++++ topologie/views.py | 33 +++++++++------------------------ 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/topologie/forms.py b/topologie/forms.py index 0119435d..39759695 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -34,7 +34,7 @@ from __future__ import unicode_literals from machines.models import Interface from django import forms -from django.forms import ModelForm +from django.forms import ModelForm, Form from .models import Port, Switch, Room, Stack, ModelSwitch, ConstructorSwitch diff --git a/topologie/models.py b/topologie/models.py index 0f277434..fca4a3be 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -37,10 +37,15 @@ la prise from __future__ import unicode_literals +import itertools + from django.db import models from django.db.models.signals import post_delete from django.dispatch import receiver from django.core.exceptions import ValidationError +from django.db import IntegrityError +from django.db import transaction +from reversion import revisions as reversion class Stack(models.Model): @@ -125,6 +130,32 @@ class Switch(models.Model): else: raise ValidationError({'stack_member_id': "L'id dans la stack\ ne peut être nul"}) + def create_ports(self, begin, end): + """ Crée les ports de begin à end si les valeurs données sont cohérentes. """ + + s_begin = s_end = 0 + nb_ports = self.ports.count() + if nb_ports > 0: + ports = self.ports.order_by('port').values('port') + s_begin = ports.first().get('port') + s_end = ports.last().get('port') + + if end < begin: + raise ValidationError("Port de fin inférieur au port de début !") + if end - begin > self.number: + raise ValidationError("Ce switch ne peut avoir autant de ports.") + begin_range = range(begin, s_begin) + end_range = range(s_end+1, end+1) + for i in itertools.chain(begin_range, end_range): + port = Port() + port.switch = self + port.port = i + try: + with transaction.atomic(), reversion.create_revision(): + port.save() + reversion.set_comment("Création") + except IntegrityError: + ValidationError("Création d'un port existant.") class ModelSwitch(models.Model): diff --git a/topologie/views.py b/topologie/views.py index 7bed18aa..64c4aeb6 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -35,14 +35,13 @@ coté models et forms de topologie """ from __future__ import unicode_literals -import itertools - from django.shortcuts import render, redirect from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.db import IntegrityError from django.db import transaction from django.db.models import ProtectedError +from django.core.exceptions import ValidationError from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from reversion import revisions as reversion from reversion.models import Version @@ -491,42 +490,28 @@ def create_ports(request, switch_id): except Switch.DoesNotExist: messages.error(request, u"Switch inexistant") return redirect("/topologie/") - + s_begin = s_end = 0 nb_ports = switch.ports.count() if nb_ports > 0: ports = switch.ports.order_by('port').values('port') s_begin = ports.first().get('port') s_end = ports.last().get('port') - + port_form = CreatePortsForm( request.POST or None, initial={'begin': s_begin, 'end': s_end} ) + if port_form.is_valid(): begin = port_form.cleaned_data['begin'] end = port_form.cleaned_data['end'] - if end < begin: - messages.error(request, "Port de fin inférieur au port de début !") - return redirect("/topologie/switch/" + str(switch.id)) - if end - begin > switch.number: - messages.error(request, "Ce switch ne peut avoir autant de ports.") - return redirect("/topologie/switch/" + str(switch.id)) + try: + switch.create_ports(begin, end) + messages.success(request, "Ports créés.") + except ValidationError as e: + messages.error(request, ''.join(e)) - begin_range = range(begin, s_begin) - end_range = range(s_end+1, end+1) - for i in itertools.chain(begin_range, end_range): - port = Port() - port.switch = switch - port.port = i - try: - with transaction.atomic(), reversion.create_revision(): - port.save() - reversion.set_user(request.user) - reversion.set_comment("Création") - messages.success(request, "Création du port %d" % i) - except IntegrityError: - messages.error(request, "Création d'un port existant.") return redirect("/topologie/switch/" + str(switch.id)) return form({'topoform': port_form}, 'topologie/switch.html', request)