Commit 2b08be89 authored by LEVY-FALK Hugo's avatar LEVY-FALK Hugo Committed by root

Utilisation de formset pour éditer une liste de ports.

parent a00ad6c5
......@@ -59,6 +59,7 @@ class EditInterfaceForm(ModelForm):
self.fields['mac_address'].label = 'Adresse mac'
self.fields['type'].label = 'Type de machine'
self.fields['type'].empty_label = "Séléctionner un type de machine"
self.fields['port_lists'].label = "Configuration des ports"
if "machine" in self.fields:
self.fields['machine'].queryset = Machine.objects.all().select_related('user')
......@@ -231,68 +232,13 @@ class VlanForm(ModelForm):
class DelVlanForm(Form):
vlan = forms.ModelMultipleChoiceField(queryset=Vlan.objects.all(), label="Vlan actuels", widget=forms.CheckboxSelectMultiple)
class EditPortForm(ModelForm):
class Meta:
model = Port
fields = '__all__'
class EditPortListForm(ModelForm):
tcp_ports_in = forms.CharField(required=False, label="Ports TCP (entrée)")
udp_ports_in = forms.CharField(required=False, label="Ports UDP (entrée)")
tcp_ports_out = forms.CharField(required=False, label="Ports TCP (sortie)")
udp_ports_out = forms.CharField(required=False, label="Ports UDP (sortie)")
class Meta:
model = PortList
fields = ['name']
def __init__(self, *args, **kwargs):
super(EditPortListForm, self).__init__(*args, **kwargs)
self.fields['name'].label = "Nom de la liste"
if 'instance' in kwargs.keys():
p = kwargs['instance']
self.fields['tcp_ports_in'].initial = ', '.join(map(str, p.tcp_ports_in()))
self.fields['tcp_ports_out'].initial = ', '.join(map(str, p.tcp_ports_out()))
self.fields['udp_ports_in'].initial = ', '.join(map(str, p.udp_ports_in()))
self.fields['udp_ports_out'].initial = ', '.join(map(str, p.udp_ports_out()))
def save(self, commit=False):
Sauvegarde l'instance. Le commit est obligatoire à cause des ForeignKey.
instance = super(EditPortListForm, self).save(commit=False)
# Suppression des anciens ports.
for port in instance.port_set.all():
split = r',\s+'
ip_range = r'\d+-\d+'
if == None: # On ne peut pas créer de ForeignKey sur des objets sans pk
def add_port(string, protocole, mode):
for p in re.split(split, string):
if not p:
if re.match(ip_range, p):
a,b = p.split('-')
a,b = int(a), int(b)
begin,end = min(a,b),max(a,b)
begin = end = int(p.strip())
port = Port()
port.begin = begin
port.end = end
port.port_list = instance
port.protocole = protocole = mode
# Ajout des ports TCP en entrée
add_port(self.cleaned_data['tcp_ports_in'], Port.TCP, Port.IN)
# Ajout des ports TCP en sortie
add_port(self.cleaned_data['tcp_ports_out'], Port.TCP, Port.OUT)
# Ajout des ports UDP en entrée
add_port(self.cleaned_data['tcp_ports_in'], Port.UDP, Port.IN)
# Ajout des ports UDP en sortie
add_port(self.cleaned_data['tcp_ports_in'], Port.UDP, Port.OUT)
if commit:
return instance
fields = '__all__'
......@@ -223,7 +223,7 @@ class Interface(models.Model):
machine = models.ForeignKey('Machine', on_delete=models.CASCADE)
type = models.ForeignKey('MachineType', on_delete=models.PROTECT)
details = models.CharField(max_length=255, blank=True)
has_public_ip = False
port_lists = models.ManyToManyField('PortList', blank=True)
def is_active(self):
......@@ -411,11 +411,10 @@ class Service_link(models.Model):
class PortList(models.Model):
"""Liste des ports ouverts sur une interface."""
interfaces = models.ManyToManyField('Interface')
name = models.CharField(help_text="Nom de la configuration des ports.", max_length=255)
def __str__(self):
return ', '.join(map(str, self.port_set.all()))
def tcp_ports_in(self):
return self.port_set.filter(protocole=Port.TCP, io=Port.IN)
{% extends "machines/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
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 %}Création et modification de machines{% endblock %}
{% block content %}
{% bootstrap_form_errors port_list %}
<form class="form" method="post">
{% csrf_token %}
{% bootstrap_form port_list %}
{{ ports.management_form }}
<div id="formset">
{% for form in ports.forms %}
<div class="port">
{{ form }}
{% endfor %}
<input class="btn btn-primary btn-sm" role="button" value="Ajouter un port" id="add_one">
{% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %}
<script type="text/javascript">
var template = `{{ports.empty_form}}`;
function add_port(){
var new_index = document.getElementsByClassName('port').length;
document.getElementById('id_form-TOTAL_FORMS').value =
parseInt(document.getElementById('id_form-TOTAL_FORMS').value) + 1;
var new_port = document.createElement('div');
new_port.className = 'port';
new_port.innerHTML = template.replace(/__prefix__/g, new_index);
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("add_one").addEventListener("click", add_port, true);});
{% endblock %}
......@@ -35,7 +35,7 @@ from django.template import Context, RequestContext, loader
from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import ProtectedError
from django.forms import ValidationError
from django.forms import ValidationError, formset_factory, modelformset_factory
from django.db import transaction
from django.contrib.auth import authenticate, login
from django.views.decorators.csrf import csrf_exempt
......@@ -48,8 +48,8 @@ from reversion.models import Version
import re
from .forms import NewMachineForm, EditMachineForm, EditInterfaceForm, AddInterfaceForm, MachineTypeForm, DelMachineTypeForm, ExtensionForm, DelExtensionForm, BaseEditInterfaceForm, BaseEditMachineForm
from .forms import EditIpTypeForm, IpTypeForm, DelIpTypeForm, DomainForm, AliasForm, DelAliasForm, NsForm, DelNsForm, TextForm, DelTextForm, MxForm, DelMxForm, VlanForm, DelVlanForm, ServiceForm, DelServiceForm, NasForm, DelNasForm
from .forms import EditPortListForm
from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList
from .forms import EditPortListForm, EditPortForm
from .models import IpType, Machine, Interface, IpList, MachineType, Extension, Mx, Ns, Domain, Service, Service_link, Vlan, Nas, Text, PortList, Port
from users.models import User
from users.models import all_has_access
from preferences.models import GeneralOption, OptionalMachine
......@@ -928,11 +928,23 @@ def edit_portlist(request, pk):
messages.error(request, "Liste de ports inexistante")
return redirect("/machines/index_portlist/")
port_list = EditPortListForm(request.POST or None, instance=port_list_instance)
if port_list.is_valid():
port_formset = modelformset_factory(
)(request.POST or None, queryset=port_list_instance.port_set.all())
if port_list.is_valid() and port_formset.is_valid():
pl =
instances =
for to_delete in port_formset.deleted_objects:
for port in instances:
port.port_list = pl
messages.success(request, "Liste de ports modifiée")
return redirect("/machines/index_portlist/")
return form({'machineform' : port_list}, 'machines/machine.html', request)
return form({'port_list' : port_list, 'ports' : port_formset}, 'machines/edit_portlist.html', request)
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