Integrate a Bootstrap File Upload Utility in Django

Integrating a standard file upload feature in Django is relatively straightforward. It's simply a case of rendering the individual image field in your Django template.

For a functional image selector, there's absolutely nothing wrong with this approach. It achieves its objective of replacing an image field with another image that a user selects from their computer's hard drive.

What about if you would like a full width selector with the name and image's location to be displayed within the image selector's form control? The image name should be displayed both when the user arrives at an update page, or following a selection of an image from their hard drive.

This isn't as trivial as it perhaps could or even should be and there are a couple of preconditions that must be met before implementing this. Firstly, you'll need to ensure that the Bootstrap stylesheet is referenced within your site's <head> tag and the Bootstrap's JS is referenced inside the closing </body> tag of your site.

# base.html

<html lang="en">
  <head>
    <!-- Meta -->
    ...

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" 
    href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" 
    integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" 
    crossorigin="anonymous">
    ...
  </head>


  <body>
    ...
    <!-- Bootstrap JS -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" 
      integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" 
      crossorigin="anonymous">
    </script>

    <!-- Additional Page Specific JavaScript -->
    {% block additional_js %}{% endblock additional_js %}
  </body>
</html>

 

An additional script will also be required to be inserted as an additonal JavaScript block beneath your {% endblock content %} tag.

{% extends 'base.html' %}
{% load static %}

{% block content %}
  Your form's content...
{% endblock content %}

{% block additional_js %}
  <!-- Functionality for selected filename from input selector to be displayed -->
  <script src={% static 'assets/js/input-filename.js' %} 
    type="application/javascript">
  </script>
{% endblock additional_js %}

 

In your create/update form code, you will need to render out each of the form fields individually. When it comes to rendering out the image field with the Bootstrap file picker, you will need to use the following code.

'form' is the name you have given to your form. The canonical way of naming your form is 'form'

'image' is the name of your image field

<!-- Post Image -->
<div class="custom-file mt-2">
  <input type="file" class="custom-file-input" name="image" accept="image/*" 
    id="{{ form.image.id_for_label }}">
  <label class="custom-file-label" for="{{ form.image.id_for_label }}">
    {% if post.image %}{{ post.image.name }}{% else %}Select Post Image...{% endif %}
  </label>
  <div class="small text-muted">{{ form.image.help_text }}</div>
  <span class="text-danger small">{{ form.image.errors }}</span>
</div>

The JavaScript code that makes this work is:

$('input[type="file"]').change(function(e){
  var fileName = e.target.files[0].name;
  $('.custom-file-label').html(fileName);
});

Reference Details

 

You can find my implementation of this at the following commit: Reference GitHub Code

Use GitHub's 'Go to file' button to look for the following files:

  • pages/templates/pages/base.html
  • pages/templates/pages/js.html
  • blog/templates/blog/components/post_create.html
  • blog/templates/blog/components/post_image_update.html
  • static/assets/js/input-filename.js

Here are the relevant Boostrap Docs

Pinned Versions: Python 3.8.3, Django 3.0.7, Bootstrap 4.5.0