How to Setup an Upload Handler for Redactor

Yesterday, I posted about how I was having fun with redactorjs and promised to follow up with how to hook up the ability to upload and embed images. Well, I am pleased to be able to show you how with a few lines of Python and Django.

Specifically, we are talking about how to hook up redactor so the image button on the toolbar presents a functioning modal like so:

There are two parts to this dialog that we are going to hook up. First, the ability to upload an image, and secondly, the ability choose one that we have previously uploaded.

The Model

There is a single, super simple model to store the files that get uploaded. The boolean flag indicating whether or not the file is an image is for the support I am going to add to be able to upload regular files as well. It's probably best for me to store an inspected mimetype, but this should suffice for now in case I want to reuse these objects elsewhere in order to know how to display them.

import datetime

from django.db import models

class File(models.Model):

    upload = models.FileField(upload_to="uploads/%Y/%m/%d/")
    date_created = models.DateTimeField(
    is_image = models.BooleanField(default=True)

The Views

There are two views to support the two bits of functionality I mentioned we'd enable. The first is a POST only view to handle the actual upload. The second one is used to return a bit of JSON with links to recent image uploads so that they can be displayed in the gallery chooser.

import json

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

from django.contrib.auth.decorators import login_required

from shiftingbits.uploads.models import File

def upload_photos(request):
    images = []
    for f in request.FILES.getlist("file"):
        obj = File.objects.create(upload=f, is_image=True)
        images.append({"filelink": obj.upload.url})
    return HttpResponse(json.dumps(images), mimetype="application/json")

def recent_photos(request):
    images = [
        {"thumb": obj.upload.url, "image": obj.upload.url}
        for obj in File.objects.filter(is_image=True).order_by("-date_created")[:20]
    return HttpResponse(json.dumps(images), mimetype="application/json")

The URLs

This is pretty self-explanatory.

from django.conf.urls import patterns, include, url

urlpatterns = patterns("",
    url(r"^ajax/photos/upload/$", "shiftingbits.uploads.views.upload_photos", name="upload_photos"),
    url(r"^ajax/photos/recent/$", "shiftingbits.uploads.views.recent_photos", name="recent_photos")

The Javascript

There are two options that you must pass the instantiation of the redactor plugin:

$("form textarea").redactor({
    imageUpload: '{% url upload_photos %}',
    imageGetJson: '{% url recent_photos %}'

That's all there is to it.