mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -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'
|
template_name = 'dcim/device_component_add.html'
|
||||||
|
|
||||||
def post(self, request):
|
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')
|
logger = logging.getLogger('netbox.dcim.views.InterfaceCreateView')
|
||||||
form = self.form(request.POST, initial=request.GET)
|
form = self.form(request.POST, initial=request.GET)
|
||||||
|
self.validate_form(request, form)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
if '_addanother' in request.POST:
|
||||||
new_components = []
|
return redirect(request.get_full_path())
|
||||||
data = deepcopy(request.POST)
|
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
|
||||||
names = form.cleaned_data['name_pattern']
|
return redirect(f'/ipam/ip-addresses/add/?interface={first_obj}&return_url={self.get_return_url(request)}')
|
||||||
labels = form.cleaned_data.get('label_pattern')
|
else:
|
||||||
for i, name in enumerate(names):
|
return redirect(self.get_return_url(request))
|
||||||
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)
|
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'component_type': self.queryset.model._meta.verbose_name,
|
'component_type': self.queryset.model._meta.verbose_name,
|
||||||
|
@ -1088,6 +1088,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|||||||
form = None
|
form = None
|
||||||
model_form = None
|
model_form = None
|
||||||
template_name = None
|
template_name = None
|
||||||
|
created_objects = []
|
||||||
|
|
||||||
def get_required_permission(self):
|
def get_required_permission(self):
|
||||||
return get_permission_for_model(self.queryset.model, 'add')
|
return get_permission_for_model(self.queryset.model, 'add')
|
||||||
@ -1105,25 +1106,47 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|||||||
def post(self, request):
|
def post(self, request):
|
||||||
logger = logging.getLogger('netbox.views.ComponentCreateView')
|
logger = logging.getLogger('netbox.views.ComponentCreateView')
|
||||||
form = self.form(request.POST, initial=request.GET)
|
form = self.form(request.POST, initial=request.GET)
|
||||||
|
self.validate_form(request, form)
|
||||||
|
|
||||||
if form.is_valid():
|
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 = []
|
new_components = []
|
||||||
data = deepcopy(request.POST)
|
data = deepcopy(request.POST)
|
||||||
|
|
||||||
names = form.cleaned_data['name_pattern']
|
names = form.cleaned_data['name_pattern']
|
||||||
labels = form.cleaned_data.get('label_pattern')
|
labels = form.cleaned_data.get('label_pattern')
|
||||||
|
|
||||||
for i, name in enumerate(names):
|
for i, name in enumerate(names):
|
||||||
label = labels[i] if labels else None
|
label = labels[i] if labels else None
|
||||||
# Initialize the individual component form
|
# Initialize the individual component form
|
||||||
data['name'] = name
|
data['name'] = name
|
||||||
data['label'] = label
|
data['label'] = label
|
||||||
|
|
||||||
if hasattr(form, 'get_iterative_data'):
|
if hasattr(form, 'get_iterative_data'):
|
||||||
data.update(form.get_iterative_data(i))
|
data.update(form.get_iterative_data(i))
|
||||||
|
|
||||||
component_form = self.model_form(data)
|
component_form = self.model_form(data)
|
||||||
|
|
||||||
if component_form.is_valid():
|
if component_form.is_valid():
|
||||||
new_components.append(component_form)
|
new_components.append(component_form)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for field, errors in component_form.errors.as_data().items():
|
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
|
# 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)))
|
form.add_error(field, '{}: {}'.format(name, ', '.join(e)))
|
||||||
|
|
||||||
if not form.errors:
|
if not form.errors:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
|
||||||
# Create the new components
|
# Create the new components
|
||||||
new_objs = []
|
|
||||||
for component_form in new_components:
|
for component_form in new_components:
|
||||||
obj = component_form.save()
|
obj = component_form.save()
|
||||||
new_objs.append(obj)
|
self.created_objects.append(obj)
|
||||||
|
|
||||||
# Enforce object-level permissions
|
# 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
|
raise ObjectDoesNotExist
|
||||||
|
|
||||||
messages.success(request, "Added {} {}".format(
|
messages.success(request, "Added {} {}".format(
|
||||||
len(new_components), self.queryset.model._meta.verbose_name_plural
|
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:
|
except ObjectDoesNotExist:
|
||||||
msg = "Component creation failed due to object-level permissions violation"
|
msg = "Component creation failed due to object-level permissions violation"
|
||||||
logger.debug(msg)
|
logger.debug(msg)
|
||||||
form.add_error(None, 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):
|
class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user