mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 03:56:53 -06:00
#2434: Refactor ComponentCreateView to use generic form validation method
New validate_form method on ComponentCreateView handles validation generically, which any post() method on ComponentCreateView can use to validate the form but handle the response differently as needed.
This commit is contained in:
parent
515aed7022
commit
2d2719cfb2
@ -1914,65 +1914,22 @@ class InterfaceCreateView(generic.ComponentCreateView):
|
||||
template_name = 'dcim/device_component_add.html'
|
||||
|
||||
def post(self, request):
|
||||
"""
|
||||
Override inherited post() method to handle request to assign newly created
|
||||
interface objects (first object) to an IP Address object.
|
||||
"""
|
||||
logger = logging.getLogger('netbox.dcim.views.InterfaceCreateView')
|
||||
form = self.form(request.POST, initial=request.GET)
|
||||
self.validate_form(request, form)
|
||||
|
||||
if form.is_valid():
|
||||
|
||||
new_components = []
|
||||
data = deepcopy(request.POST)
|
||||
|
||||
names = form.cleaned_data['name_pattern']
|
||||
labels = form.cleaned_data.get('label_pattern')
|
||||
for i, name in enumerate(names):
|
||||
label = labels[i] if labels else None
|
||||
# Initialize the individual component form
|
||||
data['name'] = name
|
||||
data['label'] = label
|
||||
if hasattr(form, 'get_iterative_data'):
|
||||
data.update(form.get_iterative_data(i))
|
||||
component_form = self.model_form(data)
|
||||
|
||||
if component_form.is_valid():
|
||||
new_components.append(component_form)
|
||||
else:
|
||||
for field, errors in component_form.errors.as_data().items():
|
||||
# Assign errors on the child form's name/label field to name_pattern/label_pattern on the parent form
|
||||
if field == 'name':
|
||||
field = 'name_pattern'
|
||||
elif field == 'label':
|
||||
field = 'label_pattern'
|
||||
for e in errors:
|
||||
form.add_error(field, '{}: {}'.format(name, ', '.join(e)))
|
||||
|
||||
if not form.errors:
|
||||
try:
|
||||
# Create the new components
|
||||
new_objs = []
|
||||
with transaction.atomic():
|
||||
for component_form in new_components:
|
||||
obj = component_form.save()
|
||||
new_objs.append(obj)
|
||||
|
||||
# Enforce object-level permissions
|
||||
if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs):
|
||||
raise ObjectDoesNotExist
|
||||
|
||||
messages.success(request, "Added {} {}".format(
|
||||
len(new_components), self.queryset.model._meta.verbose_name_plural
|
||||
))
|
||||
if '_addanother' in request.POST:
|
||||
return redirect(request.get_full_path())
|
||||
elif '_assignip' in request.POST and len(new_objs) >= 1 and request.user.has_perm('ipam.add_ipaddress'):
|
||||
first_obj = new_objs[0].pk
|
||||
return redirect(f'/ipam/ip-addresses/add/?interface={first_obj}&return_url={self.get_return_url(request)}')
|
||||
else:
|
||||
return redirect(self.get_return_url(request))
|
||||
|
||||
except ObjectDoesNotExist:
|
||||
msg = "Component creation failed due to object-level permissions violation"
|
||||
logger.debug(msg)
|
||||
form.add_error(None, msg)
|
||||
if '_addanother' in request.POST:
|
||||
return redirect(request.get_full_path())
|
||||
elif '_assignip' in request.POST and len(self.created_objects) >= 1 and request.user.has_perm('ipam.add_ipaddress'):
|
||||
first_obj = self.created_objects[0].pk
|
||||
return redirect(f'/ipam/ip-addresses/add/?interface={first_obj}&return_url={self.get_return_url(request)}')
|
||||
else:
|
||||
return redirect(self.get_return_url(request))
|
||||
|
||||
return render(request, self.template_name, {
|
||||
'component_type': self.queryset.model._meta.verbose_name,
|
||||
|
@ -1088,6 +1088,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
||||
form = None
|
||||
model_form = None
|
||||
template_name = None
|
||||
created_objects = []
|
||||
|
||||
def get_required_permission(self):
|
||||
return get_permission_for_model(self.queryset.model, 'add')
|
||||
@ -1105,25 +1106,47 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
||||
def post(self, request):
|
||||
logger = logging.getLogger('netbox.views.ComponentCreateView')
|
||||
form = self.form(request.POST, initial=request.GET)
|
||||
self.validate_form(request, form)
|
||||
|
||||
if form.is_valid():
|
||||
if '_addanother' in request.POST:
|
||||
return redirect(request.get_full_path())
|
||||
else:
|
||||
return redirect(self.get_return_url(request))
|
||||
|
||||
return render(request, self.template_name, {
|
||||
'component_type': self.queryset.model._meta.verbose_name,
|
||||
'form': form,
|
||||
'return_url': self.get_return_url(request),
|
||||
})
|
||||
|
||||
def validate_form(self, request, form):
|
||||
"""
|
||||
Validate form values and set errors on the form object as they are detected. If
|
||||
no errors are found, signal success messages.
|
||||
"""
|
||||
|
||||
logger = logging.getLogger('netbox.views.ComponentCreateView')
|
||||
if form.is_valid():
|
||||
new_components = []
|
||||
data = deepcopy(request.POST)
|
||||
|
||||
names = form.cleaned_data['name_pattern']
|
||||
labels = form.cleaned_data.get('label_pattern')
|
||||
|
||||
for i, name in enumerate(names):
|
||||
label = labels[i] if labels else None
|
||||
# Initialize the individual component form
|
||||
data['name'] = name
|
||||
data['label'] = label
|
||||
|
||||
if hasattr(form, 'get_iterative_data'):
|
||||
data.update(form.get_iterative_data(i))
|
||||
|
||||
component_form = self.model_form(data)
|
||||
|
||||
if component_form.is_valid():
|
||||
new_components.append(component_form)
|
||||
|
||||
else:
|
||||
for field, errors in component_form.errors.as_data().items():
|
||||
# Assign errors on the child form's name/label field to name_pattern/label_pattern on the parent form
|
||||
@ -1135,40 +1158,26 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
||||
form.add_error(field, '{}: {}'.format(name, ', '.join(e)))
|
||||
|
||||
if not form.errors:
|
||||
|
||||
try:
|
||||
|
||||
with transaction.atomic():
|
||||
|
||||
# Create the new components
|
||||
new_objs = []
|
||||
for component_form in new_components:
|
||||
obj = component_form.save()
|
||||
new_objs.append(obj)
|
||||
self.created_objects.append(obj)
|
||||
|
||||
# Enforce object-level permissions
|
||||
if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs):
|
||||
if self.queryset.filter(pk__in=[obj.pk for obj in self.created_objects]).count() != len(self.created_objects):
|
||||
raise ObjectDoesNotExist
|
||||
|
||||
messages.success(request, "Added {} {}".format(
|
||||
len(new_components), self.queryset.model._meta.verbose_name_plural
|
||||
))
|
||||
if '_addanother' in request.POST:
|
||||
return redirect(request.get_full_path())
|
||||
else:
|
||||
return redirect(self.get_return_url(request))
|
||||
|
||||
except ObjectDoesNotExist:
|
||||
msg = "Component creation failed due to object-level permissions violation"
|
||||
logger.debug(msg)
|
||||
form.add_error(None, msg)
|
||||
|
||||
return render(request, self.template_name, {
|
||||
'component_type': self.queryset.model._meta.verbose_name,
|
||||
'form': form,
|
||||
'return_url': self.get_return_url(request),
|
||||
})
|
||||
|
||||
|
||||
class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user