mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Merge branch 'develop' into v2-develop
Conflicts: netbox/ipam/forms.py
This commit is contained in:
@ -236,7 +236,6 @@ class PrefixFromCSVForm(forms.ModelForm):
|
|||||||
self.add_error('vlan_vid', "Invalid global VLAN ID ({}).".format(vlan_vid))
|
self.add_error('vlan_vid', "Invalid global VLAN ID ({}).".format(vlan_vid))
|
||||||
except VLAN.MultipleObjectsReturned:
|
except VLAN.MultipleObjectsReturned:
|
||||||
self.add_error('vlan_vid', "Multiple VLANs found ({} - VID {})".format(site, vlan_vid))
|
self.add_error('vlan_vid', "Multiple VLANs found ({} - VID {})".format(site, vlan_vid))
|
||||||
self.instance.vlan = vlan
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
|
||||||
@ -316,7 +315,7 @@ class IPAddressForm(BootstrapMixin, ReturnURLForm, CustomFieldForm):
|
|||||||
interface_rack = forms.ModelChoiceField(
|
interface_rack = forms.ModelChoiceField(
|
||||||
queryset=Rack.objects.all(), required=False, label='Rack', widget=APISelect(
|
queryset=Rack.objects.all(), required=False, label='Rack', widget=APISelect(
|
||||||
api_url='/api/dcim/racks/?site_id={{interface_site}}', display_field='display_name',
|
api_url='/api/dcim/racks/?site_id={{interface_site}}', display_field='display_name',
|
||||||
attrs={'filter-for': 'interface_device'}
|
attrs={'filter-for': 'interface_device', 'nullable': 'true'}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
interface_device = forms.ModelChoiceField(
|
interface_device = forms.ModelChoiceField(
|
||||||
@ -429,65 +428,6 @@ class IPAddressBulkAddForm(BootstrapMixin, CustomFieldForm):
|
|||||||
fields = ['address_pattern', 'vrf', 'tenant', 'status', 'description']
|
fields = ['address_pattern', 'vrf', 'tenant', 'status', 'description']
|
||||||
|
|
||||||
|
|
||||||
class IPAddressAssignForm(BootstrapMixin, forms.Form):
|
|
||||||
site = forms.ModelChoiceField(
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
label='Site',
|
|
||||||
required=False,
|
|
||||||
widget=forms.Select(
|
|
||||||
attrs={'filter-for': 'rack'}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
rack = forms.ModelChoiceField(
|
|
||||||
queryset=Rack.objects.all(),
|
|
||||||
label='Rack',
|
|
||||||
required=False,
|
|
||||||
widget=APISelect(
|
|
||||||
api_url='/api/dcim/racks/?site_id={{site}}',
|
|
||||||
display_field='display_name',
|
|
||||||
attrs={'filter-for': 'device', 'nullable': 'true'}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
device = forms.ModelChoiceField(
|
|
||||||
queryset=Device.objects.all(),
|
|
||||||
label='Device',
|
|
||||||
required=False,
|
|
||||||
widget=APISelect(
|
|
||||||
api_url='/api/dcim/devices/?site_id={{site}}&rack_id={{rack}}',
|
|
||||||
display_field='display_name',
|
|
||||||
attrs={'filter-for': 'interface'}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
livesearch = forms.CharField(
|
|
||||||
required=False,
|
|
||||||
label='Device',
|
|
||||||
widget=Livesearch(
|
|
||||||
query_key='q',
|
|
||||||
query_url='dcim-api:device-list',
|
|
||||||
field_to_update='device'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
interface = forms.ModelChoiceField(
|
|
||||||
queryset=Interface.objects.all(),
|
|
||||||
label='Interface',
|
|
||||||
widget=APISelect(
|
|
||||||
api_url='/api/dcim/interfaces/?device_id={{device}}'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
set_as_primary = forms.BooleanField(
|
|
||||||
label='Set as primary IP for device',
|
|
||||||
required=False
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
|
|
||||||
super(IPAddressAssignForm, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
self.fields['rack'].choices = []
|
|
||||||
self.fields['device'].choices = []
|
|
||||||
self.fields['interface'].choices = []
|
|
||||||
|
|
||||||
|
|
||||||
class IPAddressFromCSVForm(forms.ModelForm):
|
class IPAddressFromCSVForm(forms.ModelForm):
|
||||||
vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, to_field_name='rd',
|
vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, to_field_name='rd',
|
||||||
error_messages={'invalid_choice': 'VRF not found.'})
|
error_messages={'invalid_choice': 'VRF not found.'})
|
||||||
|
@ -88,20 +88,21 @@ $(document).ready(function() {
|
|||||||
// Determine the filter fields needed to make an API call
|
// Determine the filter fields needed to make an API call
|
||||||
var filter_regex = /\{\{([a-z_]+)\}\}/g;
|
var filter_regex = /\{\{([a-z_]+)\}\}/g;
|
||||||
var match;
|
var match;
|
||||||
|
var rendered_url = api_url;
|
||||||
while (match = filter_regex.exec(api_url)) {
|
while (match = filter_regex.exec(api_url)) {
|
||||||
var filter_field = $('#id_' + match[1]);
|
var filter_field = $('#id_' + match[1]);
|
||||||
if (filter_field.val()) {
|
if (filter_field.val()) {
|
||||||
api_url = api_url.replace(match[0], filter_field.val());
|
rendered_url = rendered_url.replace(match[0], filter_field.val());
|
||||||
} else if ($(this).attr('nullable') == 'true') {
|
} else if (filter_field.attr('nullable') == 'true') {
|
||||||
api_url = api_url.replace(match[0], '0');
|
rendered_url = rendered_url.replace(match[0], '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all URL variables have been replaced, make the API call
|
// If all URL variables have been replaced, make the API call
|
||||||
if (api_url.search('{{') < 0) {
|
if (rendered_url.search('{{') < 0) {
|
||||||
console.log(child_name + ": Fetching " + api_url);
|
console.log(child_name + ": Fetching " + rendered_url);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: api_url,
|
url: rendered_url,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(response, status) {
|
success: function(response, status) {
|
||||||
$.each(response.results, function(index, choice) {
|
$.each(response.results, function(index, choice) {
|
||||||
|
@ -329,13 +329,21 @@ class BulkAddView(View):
|
|||||||
new_objs = []
|
new_objs = []
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
# Validate and save each object individually
|
||||||
for value in pattern:
|
for value in pattern:
|
||||||
model_form_data[pattern_target] = value
|
model_form_data[pattern_target] = value
|
||||||
model_form = self.model_form(model_form_data)
|
model_form = self.model_form(model_form_data)
|
||||||
|
if model_form.is_valid():
|
||||||
obj = model_form.save()
|
obj = model_form.save()
|
||||||
new_objs.append(obj)
|
new_objs.append(obj)
|
||||||
except ValidationError as e:
|
else:
|
||||||
form.add_error(None, e)
|
for error in model_form.errors.as_data().values():
|
||||||
|
form.add_error(None, error)
|
||||||
|
# Abort the creation of all objects if errors exist
|
||||||
|
if form.errors:
|
||||||
|
raise ValidationError("Validation of one or more model forms failed.")
|
||||||
|
except ValidationError:
|
||||||
|
pass
|
||||||
|
|
||||||
if not form.errors:
|
if not form.errors:
|
||||||
msg = u"Added {} {}".format(len(new_objs), model._meta.verbose_name_plural)
|
msg = u"Added {} {}".format(len(new_objs), model._meta.verbose_name_plural)
|
||||||
|
Reference in New Issue
Block a user