Skip to main content

A minimal (yet careful about UX) solution to upload multiple files in a Django project, using a Django-like Form Class

Project description

django-upload-form

A minimal (yet careful about UX) solution to upload multiple files in a Django project, using a Django-like Form Class.

Purpose

The purpose of this module is that of providing a simple yet effective tool for managing the user interaction for files uploading in a Django projects, with the following features:

  1. before submission:

    • files can be added to the upload list either via drag&drop or with an file-open dialog

    • user can revise the upload list by adding or removing files

    • the list displays informations about the files (name, tipe, size)

  2. during submission:

    • image files are optionally resized up to a configurabile max resolution (TODO: recover this from “experiments” branch)

    • a progress bar is shown during files upload

  3. after submission:

    • TODO: ADD MORE DETAILS HERE

All this is obtained by leveraging HTML5 specific capabilities, and applying some clever (in my opinion) and sometimes hacky techniques I learned from a few selected articles, listed in the References section below.

No external dependencies are required (other than jQuery).

The codebase is deliberately minimal.

How to use django-upload-form

The only purpose of the package is that of:

  • managing user interaction

  • upload the files upon form submission

What you do with the uploaded files is entirely up to you, and you’re responsible for this.

These are the steps required to use django-upload-form:

  • derive your own Form class from UploadForm, and override a few methods

  • provide a view which will be the target for files upload

The UploadForm-derived class

At the very minimum, you need to override the following methods:

  • form_valid(self, request)

    Here is where you receive the list of (in-memory) uploaded files after submission; What you do with the uploaded files is entirely up to you. This method should normally return get_success_url().

  • get_success_url(self)

    Determine the URL to redirect to when the form is successfully validated.

  • get_action(self)

    Returns the url of the target view (see below).

The target view

The target view will receive the uploaded files with a POST request, and normally should:

  • build a bounded form

  • validate it

  • invoke form_valid()

You will probably use the same view for form rendering (GET); this is quite common practice, but entirely optional.

Example (‘test_view’):

def test_view(request):

    if request.method == 'GET':
        form = TestUploadForm()
    else:
        form = TestUploadForm(request.POST, request.FILES)
        if form.is_valid():
            url = form.form_valid(request)
            return JsonResponse({'action': 'redirect', 'url': url, })
        else:
            return JsonResponse({'action': 'replace', 'html': form.as_html(request), })

    return render(
        request,
        'upload_form/test_view.html', {
            'form': form,
            'form_as_html': form.as_html(request),
        }
    )

Installation

Install the package from Python Package Index running:

pip install django-upload-form

or from GitHub:

pip install git+https://github.com/morlandi/django-upload-form@master

then add ‘upload_form’ to your INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    'upload_form',
]

Sample usage

The upoad_form app provides a sample test view which uploads multiple files for illustration purposes.

You can run, study, and possibly duplicate it for further customizations.

To use it, add this to your main urls mapping:

file urls.py:

urlpatterns = [
    ...
    path('upload_form/', include('upload_form.urls', namespace='upload_form')),
    ...
]

then visit this url:

http://127.0.0.1:8000/upload_form/test/

Below is the source code of the whole test.

file upload_form/views.py

from django.shortcuts import render
try:
    from django.urls import reverse
except ModuleNotFoundError as e:
    # for Django < v1.10
    from django.core.urlresolvers import reverse
from django.http import JsonResponse
from .forms import UploadForm


class TestUploadForm(UploadForm):

    def form_valid(self, request):
        print("*")
        print("* TestUploadForm.form_valid() ...")
        print("* Here, we just log the list of received files;")
        print("* What you do with these files in a real project is entirely up to you.")
        print("*")
        self.dump()
        return self.get_success_url(request)

    def get_success_url(self, request=None):
        return '/'

    def get_action(self):
        return reverse('upload_form:test_view')


def test_view(request):

    if request.method == 'GET':
        form = TestUploadForm()
    else:
        form = TestUploadForm(request.POST, request.FILES)
        if form.is_valid():
            url = form.form_valid(request)
            return JsonResponse({'action': 'redirect', 'url': url, })
        else:
            return JsonResponse({'action': 'replace', 'html': form.as_html(request), })

    return render(
        request,
        'upload_form/test_view.html', {
            'form': form,
            'form_as_html': form.as_html(request),
        }
    )

file templates/upload_form/test.html

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


{% block extrajs %}
    {{form.media}}
{% endblock %}


{% block content %}

    <div class="container">
        <div class="row">
            <div id="upload-box" class="text-center col-md-6 col-md-offset-3" style="">

                {{ form_as_html }}

            </div>
        </div>
    </div>

{% endblock content %}

App Settings

Some settings are provided for optional customization.

The library will search these settings in the following order:

UPLOAD_FORM_MAX_FILE_SIZE_MB = 12
UPLOAD_FROM_ALLOWED_FILE_TYPES = "png jpg jpeg gif"

or:

CONSTANCE_CONFIG = {
    ...
    'UPLOAD_FORM_MAX_FILE_SIZE_MB': (12, 'Dimensione massima files in upload (MB)'),
    'UPLOAD_FROM_ALLOWED_FILE_TYPES': ("png jpg jpeg gif", "Tipi di files abilitati all'upload"),
}

Screenshots

screenshots/001.png screenshots/002.png screenshots/003.png screenshots/004.png

License

The app is intended to be open source.

Feel free to use it we at your will with no restrictions at all.

References

History

v0.3.1

  • fix Readme to keep twine happy

v0.3.0

  • published on PyPI

v0.2.3

  • prepare for publishing on PyPI

v0.2.2

  • improved Readme

v0.2.1

  • package renamed “django-upload-form” (was “django_upload_form”)

  • cleanup

  • improved documentation

v0.2.0

  • fixes for Django 2.x

  • user can now add more file to the list before submission

v0.0.5

  • green send button

v0.0.4

  • App settings removed

v0.0.3

  • Minor fixes

v0.0.2

  • Italian translation added

v0.0.1

  • Basic release

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

django_upload_form-0.3.1-py2.py3-none-any.whl (14.1 kB view hashes)

Uploaded Python 2 Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page