1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Add FileVar for file uploads

This commit is contained in:
Jeremy Stretch
2019-08-16 15:27:58 -04:00
parent 99394de14e
commit de770faf6a
3 changed files with 27 additions and 13 deletions

View File

@ -21,13 +21,14 @@ from .forms import ScriptForm
__all__ = [ __all__ = [
'BooleanVar',
'FileVar',
'IntegerVar',
'IPNetworkVar',
'ObjectVar',
'Script', 'Script',
'StringVar', 'StringVar',
'TextVar', 'TextVar',
'IntegerVar',
'BooleanVar',
'ObjectVar',
'IPNetworkVar',
] ]
@ -145,6 +146,13 @@ class ObjectVar(ScriptVariable):
self.form_field = TreeNodeChoiceField self.form_field = TreeNodeChoiceField
class FileVar(ScriptVariable):
"""
An uploaded file.
"""
form_field = forms.FileField
class IPNetworkVar(ScriptVariable): class IPNetworkVar(ScriptVariable):
""" """
An IPv4 or IPv6 prefix. An IPv4 or IPv6 prefix.
@ -193,12 +201,12 @@ class Script:
def run(self, data): def run(self, data):
raise NotImplementedError("The script must define a run() method.") raise NotImplementedError("The script must define a run() method.")
def as_form(self, data=None): def as_form(self, data=None, files=None):
""" """
Return a Django form suitable for populating the context data required to run this Script. Return a Django form suitable for populating the context data required to run this Script.
""" """
vars = self._get_vars() vars = self._get_vars()
form = ScriptForm(vars, data) form = ScriptForm(vars, data, files)
return form return form
@ -260,7 +268,7 @@ def is_variable(obj):
return isinstance(obj, ScriptVariable) return isinstance(obj, ScriptVariable)
def run_script(script, data, commit=True): def run_script(script, data, files, commit=True):
""" """
A wrapper for calling Script.run(). This performs error handling and provides a hook for committing changes. It A wrapper for calling Script.run(). This performs error handling and provides a hook for committing changes. It
exists outside of the Script class to ensure it cannot be overridden by a script author. exists outside of the Script class to ensure it cannot be overridden by a script author.
@ -269,6 +277,10 @@ def run_script(script, data, commit=True):
start_time = None start_time = None
end_time = None end_time = None
# Add files to form data
for field_name, fileobj in files.items():
data[field_name] = fileobj
try: try:
with transaction.atomic(): with transaction.atomic():
start_time = time.time() start_time = time.time()

View File

@ -400,13 +400,13 @@ class ScriptView(PermissionRequiredMixin, View):
return HttpResponseForbidden() return HttpResponseForbidden()
script = self._get_script(module, name) script = self._get_script(module, name)
form = script.as_form(request.POST) form = script.as_form(request.POST, request.FILES)
output = None output = None
execution_time = None execution_time = None
if form.is_valid(): if form.is_valid():
commit = form.cleaned_data.pop('_commit') commit = form.cleaned_data.pop('_commit')
output, execution_time = run_script(script, form.cleaned_data, commit) output, execution_time = run_script(script, form.cleaned_data, request.FILES, commit)
return render(request, 'extras/script.html', { return render(request, 'extras/script.html', {
'module': module, 'module': module,

View File

@ -57,9 +57,11 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% if execution_time %}
<div class="panel-footer text-right text-muted"> <div class="panel-footer text-right text-muted">
<small>Exec time: {{ execution_time|floatformat:3 }}s</small> <small>Exec time: {{ execution_time|floatformat:3 }}s</small>
</div> </div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
@ -72,7 +74,7 @@
You do not have permission to run scripts. You do not have permission to run scripts.
</div> </div>
{% endif %} {% endif %}
<form action="" method="post" class="form form-horizontal"> <form action="" method="post" enctype="multipart/form-data" class="form form-horizontal">
{% csrf_token %} {% csrf_token %}
{% if not form.requires_input %} {% if not form.requires_input %}
<div class="alert alert-info"> <div class="alert alert-info">