0

My index.html file contains one large form which gets tons of user input. Towards the end of the form, I want to give the user an option to upload a file using a button. But this should not trigger the form submission because they may want to continue entering data into other parts of the form. Here is a basic overview of the HTML:

((some other stuff))
<form id="outer_form">
    ((other HTML stuff))
    <form enctype="multipart/form-data" method="post" action="{% url 'my_app:upload_file' %}" id="file-upload-form">
        {% csrf_token %}
        <input type="file" name="file" style="display: none">
        <button type="button" class="btn btn-primary" id="btn-upload-file">Upload file</button>
    </form>
    ((more other stuff))
    ((submit button for the outer form))
</form>
((other stuff))

Of course, this won't work because I have nested FORM elements which is illegal. How can I combine these two ideas, keeping the CSFR token and using the correct django action for the upload button? Thanks!

gnat79
  • 57
  • 4

2 Answers2

0

You'll need a javascript function to do what you want. To start do something like:

function submitForm(action) {
  var form = document.getElementById('form1');
  form.action = action;
  form.submit();
}

Then for your buttons give them an onclick = submitForm('{% url 'urlyourusing' %}')"

Your CSFR should carry over. If it doesn't you'll need to define it in a ajax call.

You'll also need to make sure to include the javascript in your html. Like the following example.

<script src= "{% static '/search/buttonsubmit.js' %}" type="text/javascript"></script>
user1470034
  • 671
  • 2
  • 8
  • 23
0

If there is no value in knowing the file on the backend side before form submission (meaning parsing the file will not modify the form in any way or give you an advantage) you could "just" keep that file with the rest of the form fields and only submit it when the actual submit button is pressed for the overall form and remove the separate upload button.

If you need to have that still, first you will need to have to have the django backend functionality to accept a file upload (usually separate from the POSTed to view unless you check everything in one view and in the HTML you will need to connect the Upload button to an AJAX call.

[EDIT] There are a few topics that handle AJAX calls to Django, one if which Django JQuery Ajax File Upload But I am slightly lost on the current affairs of CSRF in an AJAX call.

jQuery will make your life easier there but even with vanilla Javascript you can do it, using some of the information provided in Javascript AJAX call, ignore the PHP side.

You can add the link to the onlick event either in the button itself

<button type="button" class="btn btn-primary" id="btn-upload-file" onclick="uploadImage()">Upload file</button>

or attach it "later" in javascript

document.getElementById('btn-upload-file').onclick(uploadImage())

You will need to deal with the file similarily like in the linked question by accessing the file using an id tag, otherwise it will be harder to obtain the contents, e.g.

<input type="file" name="file" id="upload-file" style="display: none">

Please comment if you have trouble with the Django side, not knowing if you have a model behind it it is harder to propose the right thing.

d parolin
  • 194
  • 6
  • I used parts of both solutions, but in the end, I decided to simplify greatly and avoid all the javascript. I decided that the server could validate the file at the time when the entire form got submitted, and that made life a lot easier. Thanks for the help! – gnat79 Jun 05 '18 at 16:37