Skip to content

Commit

Permalink
Closes #648: Pre-populate forms when selecting "create and add another"
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Dec 6, 2019
1 parent b05566e commit 2956eff
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 24 deletions.
1 change: 1 addition & 0 deletions docs/release-notes/version-2.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ PATCH) to maintain backward compatibility. This behavior will be discontinued be
## Enhancements

* [#33](https://github.com/digitalocean/netbox/issues/33) - Add ability to clone objects (pre-populate form fields)
* [#648](https://github.com/digitalocean/netbox/issues/648) - Pre-populate forms when selecting "create and add another"
* [#792](https://github.com/digitalocean/netbox/issues/792) - Add power port and power outlet types
* [#1865](https://github.com/digitalocean/netbox/issues/1865) - Add console port and console server port types
* [#2902](https://github.com/digitalocean/netbox/issues/2902) - Replace `supervisord` with `systemd`
Expand Down
23 changes: 2 additions & 21 deletions netbox/utilities/templatetags/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.urls import reverse

from extras.models import ExportTemplate
from utilities.utils import prepare_cloned_fields

register = template.Library()

Expand All @@ -24,27 +25,7 @@ def import_button(url):
def clone_button(url, instance):

url = reverse(url)

# Populate form field values
params = {}
for field_name in getattr(instance, 'clone_fields', []):
field = instance._meta.get_field(field_name)
field_value = field.value_from_object(instance)

# Swap out False with URL-friendly value
if field_value is False:
field_value = ''

# Omit empty values
if field_value not in (None, ''):
params[field_name] = field_value

# Copy tags
if hasattr(instance, 'tags'):
params['tags'] = ','.join([t.name for t in instance.tags.all()])

# Append parameters to URL
param_string = '&'.join(['{}={}'.format(k, v) for k, v in params.items()])
param_string = prepare_cloned_fields(instance)
if param_string:
url = '{}?{}'.format(url, param_string)

Expand Down
30 changes: 30 additions & 0 deletions netbox/utilities/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,33 @@ def to_meters(length, unit):
return length * 0.3048
if unit == CableLengthUnitChoices.UNIT_INCH:
return length * 0.3048 * 12


def prepare_cloned_fields(instance):
"""
Compile an object's `clone_fields` list into a string of URL query parameters. Tags are automatically cloned where
applicable.
"""
params = {}
for field_name in getattr(instance, 'clone_fields', []):
field = instance._meta.get_field(field_name)
field_value = field.value_from_object(instance)

# Swap out False with URL-friendly value
if field_value is False:
field_value = ''

# Omit empty values
if field_value not in (None, ''):
params[field_name] = field_value

# Copy tags
if hasattr(instance, 'tags'):
params['tags'] = ','.join([t.name for t in instance.tags.all()])

# Concatenate parameters into a URL query string
param_string = '&'.join(
['{}={}'.format(k, v) for k, v in params.items()]
)

return param_string
10 changes: 7 additions & 3 deletions netbox/utilities/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import json
import sys
import yaml
from copy import deepcopy

from django.conf import settings
Expand Down Expand Up @@ -28,7 +26,7 @@
from extras.querysets import CustomFieldQueryset
from utilities.exceptions import AbortTransaction
from utilities.forms import BootstrapMixin, CSVDataField
from utilities.utils import csv_format
from utilities.utils import csv_format, prepare_cloned_fields
from .error_handlers import handle_protectederror
from .forms import ConfirmationForm, ImportForm
from .paginator import EnhancedPaginator
Expand Down Expand Up @@ -238,6 +236,12 @@ def post(self, request, *args, **kwargs):
messages.success(request, mark_safe(msg))

if '_addanother' in request.POST:

# If the object has clone_fields, pre-populate a new instance of the form
if hasattr(obj, 'clone_fields'):
url = '{}?{}'.format(request.path, prepare_cloned_fields(obj))
return redirect(url)

return redirect(request.get_full_path())

return_url = form.cleaned_data.get('return_url')
Expand Down

0 comments on commit 2956eff

Please sign in to comment.