• Stars
    star
    281
  • Rank 147,023 (Top 3 %)
  • Language
    JavaScript
  • License
    Other
  • Created over 13 years ago
  • Updated 12 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Ajax-based, multiple-upload django class with pluggable backends, and subclass goodness.

django-ajax-uploader provides a useful class you can use to easily implement ajax uploads.

It uses valum's great uploader: https://github.com/valums/file-uploader, and draws heavy inspiration and some code from https://github.com/alexkuhl/file-uploader.

You can also use fineuploader, the commercial/open source project that sprung out of valum's original work. It's great, and highly recommended.

In short, it implements a callable class, AjaxFileUploader that you can use to handle uploads. By default, AjaxFileUploader assumes you want to upload to local storage, but you can select any other backend if desired or write your own (see backends section below). Pull requests welcome!

Updates

Version 0.3.x is released, and contains:

  • Support for direct to s3 backends
  • Official deprecation of the included fileuploader.js. Please use fineuploader going forward.

Installation and Usage

You have two basic ways to set up django-ajax-uploader.

Usage (standard, non-direct to s3 backends)

Step 1. Install django-ajax-uploader.

It's in pypi now, so simply:

  • pip install ajaxuploader

You may also need to install backend-specific dependences.

  • For the S3 backend or direct S3 uploads, you will need boto. ( pip install boto )
  • For the MongoDB GridFS backend, you will need pymongo ( pip install pymongo )

Step 2. (Django 1.3+)

Add 'ajaxuploader' to your installed apps in settings.py:

INSTALLED_APPS = (
    ...
    "ajaxuploader",
)

Then:

$ python manage.py collectstatic

Step 3. Include it in your app's views and urls.

You'll need to make sure to meet the csrf requirements to still make valum's uploader work. Code similar to the following should work:

views.py

from django.middleware.csrf import get_token
from django.shortcuts import render_to_response
from django.template import RequestContext

from ajaxuploader.views import AjaxFileUploader


def start(request):
    csrf_token = get_token(request)
    return render_to_response('import.html',
        {'csrf_token': csrf_token}, context_instance = RequestContext(request))

import_uploader = AjaxFileUploader()

urls.py

url(r'start$', views.start, name="start"),
url(r'ajax-upload$', views.import_uploader, name="my_ajax_upload"),

Step 4. Set up your template.

This sample is included in the templates directory, but at the minimum, you need:

<!doctype html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" ></script>
        <script src="{{ STATIC_URL }}ajaxuploader/js/fileuploader.js" ></script>
        <link href="{{ STATIC_URL }}ajaxuploader/css/fileuploader.css" media="screen" rel="stylesheet" type="text/css" />
        <script>
            $(function(){
            var uploader = new qq.FileUploader({
                action: "{% url my_ajax_upload %}",
                element: $('#file-uploader')[0],
                multiple: true,
                onComplete: function(id, fileName, responseJSON) {
                    if(responseJSON.success) {
                        alert("success!");
                    } else {
                        alert("upload failed!");
                    }
                },
                onAllComplete: function(uploads) {
                    // uploads is an array of maps
                    // the maps look like this: {file: FileObject, response: JSONServerResponse}
                    alert("All complete!");
                },
                params: {
                    'csrf_token': '{{ csrf_token }}',
                    'csrf_name': 'csrfmiddlewaretoken',
                    'csrf_xname': 'X-CSRFToken',
                },
            });
            });
        </script>
    </head>
<body>
    <div id="file-uploader">       
        <noscript>          
            <p>Please enable JavaScript to use file uploader.</p>
        </noscript>         
    </div>
</body>
</html>

If you want to use the latest version of Fine Uploader, as valum's file-uploader is now called, instead of the one bundled with django-ajax-uploader, you can do so by replacing the params arguments in the above template with the following customHeaders:

                ...
                customHeaders: {
                    'X-CSRFToken': '{{ csrf_token }}',
                },
                ...

Usage (Direct to S3 uploads)

Step 1. Install django-ajax-uploader and dependencies.

  • pip install ajaxuploader boto

Step 2. Set up any necessary keys at AWS

Fineuploader has a great tutorial here.

Step 3. Include it in your app's settings and urls

Add 'ajaxuploader' to your installed apps in settings.py

INSTALLED_APPS = (
    ...
    "ajaxuploader",
)

Also in settings, add the following:

AWS_UPLOAD_BUCKET_NAME = "bucket-to-upload-to"
AWS_UPLOAD_CLIENT_KEY = "public-aws-upload-key"
AWS_UPLOAD_CLIENT_SECRET_KEY = "secret-aws-upload-key"

In your urls.py, add:

url(r'^ajax-uploader/', include('ajaxuploader.urls', namespace='ajaxuploader', app_name='ajaxuploader')),

Then:

$ python manage.py collectstatic

Step 4. Set up your template.

You can pretty much just use the same examples as are on fineuploader's site. Make sure to pass in AWS_UPLOAD_CLIENT_KEY and AWS_UPLOAD_BUCKET_NAME to the template, and something like this should work:

<div id="fine_uploader"></div>

<script>
var uploader = new qq.s3.FineUploader({
    element: document.getElementById('fine_uploader'),
    request: {
        endpoint: '{{ AWS_UPLOAD_BUCKET_NAME }}.s3.amazonaws.com',
        accessKey: AWS_CLIENT_ACCESS_KEY
    },
    signature: {
        endpoint: '{% url "ajaxuploader:s3_signature" %}'
    },
    uploadSuccess: {
        endpoint: '{% url "ajaxuploader:s3_success" %}'
    },
    iframeSupport: {
        localBlankPagePath: '/success.html'
    },
    deleteFile: {
        enabled: true,
        endpoint: '{% url "ajaxuploader:s3_delete" %}'
    },
});
</script>

Backends

django-ajax-uploader can put the uploaded files into a number of places, and perform actions on the files uploaded. Currently, there are backends available for local storage (default), Amazon S3, MongoDB (GridFS), CouchDB, and a locally stored image thumbnail backend. Creating a custom backend is fairly straightforward, and pull requests are welcome.

Built-in Backends

django-ajax-uploader has the following backends:

local.LocalUploadBackend

Stores the file locally, by default to {MEDIA_ROOT}/uploads.

Requirements:

  • None

Settings:

  • UPLOAD_DIR : The directory to store the uploaded file in, within MEDIA_ROOT. Defaults to "uploads".
  • BUFFER_SIZE: The size of each chunk to write. Defaults to 10 MB. See the caveat at the bottom before changing it.

Context returned:

  • path: The full media path to the uploaded file.

mongodb.MongoDBUploadBackend

Stores the file in MongoDB via GridFS

Requirements

Settings:

  • AJAXUPLOAD_MONGODB_HOST: Specify either a single host:port or a list of host:port. Defaults to "localhost:27017"
  • AJAXUPLOAD_MONGODB_PORT (for backwards compatibility): Specify the port of your MongoDB server. Defaults to 27017 if not specified.
  • AJAXUPLOAD_MONGODB_REPLICASET (optional): Specify the name of your replicaset as a string. Defaults to an empty string.
# Replicaset
AJAXUPLOAD_MONGODB_HOST = ["127.0.0.1:27017", "127.0.0.1:27018"]
AJAXUPLOAD_MONGODB_REPLICASET = "myset"

# Standard
AJASUPLOAD_MONGODB_HOST = "127.0.0.1:27017"

Arguments

  • db (required): Specify the database within MongoDB you wish to use
  • collection (optional): Specify the collection within the db you wish to use. This is optional and will default to fs if not specified

Context returned:

  • None

couch.CouchDBUploadBackend

Stores the file in a CouchDB backend

Requirements

Settings:

  • AJAXUPLOAD_COUCHDB_HOST: Specify the host of your CouchDB server. Defaults to http://localhost:5984 if not specified.

Arguments

  • db (required): Specify the database within CouchDB you wish to use

Context returned:

  • None

s3.S3UploadBackend

Stores the file in Amazon's S3.

Requirements:

Settings:

  • NUM_PARALLEL_PROCESSES : Uploads to Amazon are parallelized to increase speed. If you have more cores and a big pipe, increase this setting for better performance. Defaults to 4.
  • BUFFER_SIZE: The size of each chunk to write. Defaults to 10 MB.

Context returned:

  • None

thumbnail.ThumbnailUploadBackend

Stores a thumbnail of the locally, optionally discarding the upload. Subclasses LocalUploadBackend.

Requirements:

Settings:

  • DIMENSIONS : A string of the dimensions (WxH) to resize the uploaded image to. Defaults to "100x100"
  • KEEP_ORIGINAL: Whether to keep the originally uploaded file. Defaults to False.
  • BUFFER_SIZE: The size of each chunk to write. Defaults to 10 MB.

Context returned:

  • path: The full media path to the uploaded file.

easythumbnails.EasyThumbnailUploadBackend

Stores a thumbnail of the locally, optionally discarding the upload. Uses 'Easy Thumbnails' rather than sorl-thumbnail, which requires a key-value store. Subclasses LocalUploadBackend.

Requirements:

Settings:

  • DIMENSIONS : A tuple of the dimensions (WxH) to resize the uploaded image to. Defaults to "100x100"
  • KEEP_ORIGINAL: Whether to keep the originally uploaded file. Defaults to False.
  • CROP: Whether to create a 'cropped' version of the thumbnail. Defaults to True.
  • BUFFER_SIZE: The size of each chunk to write. Defaults to 10 MB.

Context returned:

  • path: The full media path to the uploaded file.

default_storage.DefaultStorageUploadBackend

This backend uses Django's default storage backend (defined by the DEFAULT_FILE_STORAGE setting) to save the uploaded files.

Requirements:

  • None

Settings:

  • UPLOAD_DIR : The directory to store the uploaded file in, within MEDIA_ROOT. Defaults to "uploads".
  • BUFFER_SIZE: The size in bytes of each chunk to write. Defaults to 10 MB; i.e. 10485760 bytes. See the caveat at the bottom before changing it.

Context returned:

  • path: The full media path to the uploaded file.

Example Usage:

#views.py
from ajaxuploader.views import AjaxFileUploader
from ajaxuploader.backends.easythumbnails import EasyThumbnailUploadBackend

import_uploader = AjaxFileUploader(UPLOAD_DIR='my_upload', backend=EasyThumbnailUploadBackend, DIMENSIONS=(250, 250)) 

Backend Usage

The default backend is local.LocalUploadBackend. To use another backend, specify it when instantiating AjaxFileUploader.

For instance, to use MongoDBUploadBackend:

views.py

from ajaxuploader.views import AjaxFileUploader
from ajaxuploader.backends.mongodb import MongoDBUploadBackend

...
import_uploader = AjaxFileUploader(backend=MongoDBUploadBackend, db='uploads')

To set custom parameters, simply pass them along with instantiation. For example, for larger thumbnails, preserving the originals: views.py

from ajaxuploader.backends.thumbnail import ThumbnailUploadBackend

...
import_uploader = AjaxFileUploader(backend=ThumbnailUploadBackend, DIMENSIONS="500x500", KEEP_ORIGINAL=True)

Custom Backends

To write a custom backend, simply inherit from backends.base.AbstractUploadBackend and implement the upload_chunk method. All possible methods to override are described below.

  • upload_chunk - takes a string, and writes it to the specified location.
  • setup: takes the original filename, does all pre-processing needed before uploading the file (for example, for the S3 backend, this method is used to establish a connection with the S3 server).
  • update_filename: takes the request object and the original name of the file being updated, can return a new filename which will be used to refer to the file being saved. If undefined, the uploaded filename is used. If not overriden by upload_complete, this value will be returned in the response.
  • upload_complete: receives the request object and the filename post update_filename and does any cleanup or manipulation after the upload is complete. (Examples: cropping the image, disconnecting from the server). If a dict is returned, it is used to update the response returned to the client.

Signals

The signal ajaxuploader.signals.file_uploaded will be fired after a file has been sucessfully uploaded.

Listener methods receives two arguments: the backend that stored the file, and the upload's request.

    from django.db import models
    from django.dispatch import receiver

    from ajaxuploader.views import AjaxFileUploader
    from ajaxuploader.signals import file_uploaded


    class MyModel(models.Model):
        user = models.ForeignKey('auth.User')
        document = models.FileField(upload_to='attachments/%Y/%m/%d')


    @receiver(file_uploaded, sender=AjaxFileUploader)
    def create_on_upload(sender, backend, request, **kwargs):
        MyModel.objects.create(user=request.user, document=backend.path)

Caveats

BUFFER_SIZE - some users have reported problems using smaller buffer sizes. I also saw random failed uploads with very small sizes like 32k. 10MB has been completely reliable for me, and in what I've read here and there, so do some testing if you want to try a different value. Note that this doesn't have a big impact on the overall upload speed.

Credits and Updates

Many thanks to all for writing such helpful and readable code!

0.3.8

0.3.7

  • Fixes to UPLOAD_DIR handling and docs by dogstick

0.3.6

  • More robust handling of fineuploader vs valum's by mbaechtold

0.3.5

Long before I switched to this update format:

Original implementation and ongoing maintenance by skoczen, courtesy of GoodCloud. Most of the backend abstraction was written by chromano and shockflash.
MongoDB support and saner defaults by chrisjones-brack3t.
Threadsafe improvements and bugfixes by dwaiter.
CouchDB support by paepke. Default Storage backend by fhahn.
EasyThumbnail backend by Miserlou.
File number limit in upload by qnub.
JSON parsing improvements by onyxfish.
JSON content type added by majdal.
Improvements to Local backend by OnlyInAmerica.
Multiple upload improvements by truetug. Better subclassable backends by minddust. Addition of direct S3 support by skoczen, courtesy of GreenKahuna.

This code began as such a trivial layer on top of valum's uploader, boto, and alex's ideas it's silly. However, I didn't find any implementations that just worked, so hopefully it's useful to someone else. I also drew from these sources:

Past Release History / API Changes

Version 0.3.5 is released, with the following backward incompababile changes:

  • The EasyThumbnail backend now lives in easythumbnails.py, instead of easy_thumbnails.py.

Version 0.2.1 is released, and contains:

  • JSON parsing of extra_context now properly handles datetimes. (Thanks to onyxfish)

Version 0.2 is released, and contains:

  • Optional fileLimit param for the uploader, to limit the number of allowed files. (Thanks to qnub)
  • fhahn's default_storage backend.

Version 0.1.1 is released, and contains:

  • Support for a CouchDB backend
  • A backwards-incompatible change to the location of the ajaxuploader static files. I try to avoid backwards incompatibilities, but since /js and /css are the proper conventions and the lib is relatively young, it seemed better to get things right now, instead of waiting. The static files are now at:
    • {{STATIC_URL}}ajaxuploader/js/fileuploader.js
    • {{STATIC_URL}}ajaxuploader/css/fileuploader.css

More Repositories

1

will

Will is a simple, beautiful-to-code bot for slack, hipchat, and a whole lot more.
Python
406
star
2

django-seo-js

SEO support for react, Vue, angular, backbone, ember.us, and other SPA apps built with django.
Python
203
star
3

polytester

Polytester is a simple, easy-to-use multi-language test runner.
Python
103
star
4

django-longer-username

An app to easily provide a longer username field for django.
Python
63
star
5

mindful-browsing

A chrome extension to beautifully interrupt mindless browsing and get you back to life.
Python
34
star
6

correlationbot

The simplest way to find insights in data.
Python
4
star
7

qi-toolkit

A collection of tools and scripts we use for development. Mostly django/python/js - focused
Python
3
star
8

poemhub

Poemhub is the place to read and write poetry.
Python
2
star
9

system-recovery

in case of emergency/destroyed computer, here's what I need to get my general dev env running.
2
star
10

impact4-client

Impact4 Client
ActionScript
2
star
11

my-will

The will that helps me out in everyday life.
Python
2
star
12

skoczen

The codebase for stevenskoczen.com, including the steven manual.
Python
1
star
13

weexist

weexist.com
Python
1
star
14

impact4-builder

Impact4 Builder
ActionScript
1
star
15

mycelium

The framework that runs GoodCloud accounts
Python
1
star
16

qi-server

Quantum Imagery nginx server template
Shell
1
star
17

impact4-server

Impact4 Server
1
star
18

pdxschoolhack

My project for hackforportlandschools.com
Python
1
star
19

encore-poem

encore-poem
JavaScript
1
star
20

artechetype

A base project, ready to fork for various online projects of visual and wordual nature.
CSS
1
star
21

the-steven-manual

Python
1
star
22

isenough

isenough.com
Python
1
star
23

inkblock

A simple end-to-end publishing platform.
HTML
1
star
24

pileus

Public-facing sites for GoodCloud
JavaScript
1
star
25

footprints

Footprints is a simple, beautiful publication app.
Python
1
star