diff --git a/fileupload/models.py b/fileupload/models.py index 63a3b0e..f28d242 100644 --- a/fileupload/models.py +++ b/fileupload/models.py @@ -1,13 +1,14 @@ +# encoding: utf-8 from django.db import models -class Picture(models.Model): - # This is a small demo using just two fields. The slug field is really not - # necessary, but makes the code simpler. ImageField depends on PIL or - # pillow (where Pillow is easily installable in a virtualenv. If you have - # problems installing pillow, use a more generic FileField instead. +class Picture(models.Model): + """This is a small demo using just two fields. The slug field is really not + necessary, but makes the code simpler. ImageField depends on PIL or + pillow (where Pillow is easily installable in a virtualenv. If you have + problems installing pillow, use a more generic FileField instead. - #file = models.FileField(upload_to="pictures") + """ file = models.ImageField(upload_to="pictures") slug = models.SlugField(max_length=50, blank=True) @@ -22,7 +23,7 @@ def save(self, *args, **kwargs): self.slug = self.file.name super(Picture, self).save(*args, **kwargs) - # remove to leave file. def delete(self, *args, **kwargs): + """delete -- Remove to leave file.""" self.file.delete(False) super(Picture, self).delete(*args, **kwargs) diff --git a/fileupload/response.py b/fileupload/response.py new file mode 100644 index 0000000..829685a --- /dev/null +++ b/fileupload/response.py @@ -0,0 +1,38 @@ +# encoding: utf-8 +from django.http import HttpResponse +from django.utils import simplejson + +MIMEANY = '*/*' +MIMEJSON = 'application/json' +MIMETEXT = 'text/plain' + + +def response_mimetype(request): + """response_mimetype -- Return a proper response mimetype, accordingly to + what the client accepts, as available in the `HTTP_ACCEPT` header. + + request -- a HttpRequest instance. + + """ + can_json = MIMEJSON in request.META['HTTP_ACCEPT'] + can_json |= MIMEANY in request.META['HTTP_ACCEPT'] + return MIMEJSON if can_json else MIMETEXT + + +class JSONResponse(HttpResponse): + """JSONResponse -- Extends HTTPResponse to handle JSON format response. + + This response can be used in any view that should return a json stream of + data. + + Usage: + + def a_iew(request): + content = {'key': 'value'} + return JSONResponse(content, mimetype=response_mimetype(request)) + + """ + def __init__(self, obj='', json_opts=None, mimetype=MIMEJSON, *args, **kwargs): + json_opts = json_opts if isinstance(json_opts, dict) else {} + content = simplejson.dumps(obj, **json_opts) + super(JSONResponse, self).__init__(content, mimetype, *args, **kwargs) diff --git a/fileupload/serialize.py b/fileupload/serialize.py new file mode 100644 index 0000000..4494e79 --- /dev/null +++ b/fileupload/serialize.py @@ -0,0 +1,38 @@ +# encoding: utf-8 +import mimetypes +import re +from django.core.urlresolvers import reverse + + +def order_name(name): + """order_name -- Limit a text to 20 chars length, if necessary strips the + middle of the text and substitute it for an ellipsis. + + name -- text to be limited. + + """ + name = re.sub(r'^.*/', '', name) + if len(name) <= 20: + return name + return name[:10] + "..." + name[-7:] + + +def serialize(instance, file_attr='file'): + """serialize -- Serialize a Picture instance into a dict. + + instance -- Picture instance + file_attr -- attribute name that contains the FileField or ImageField + + """ + obj = getattr(instance, file_attr) + return { + 'url': obj.url, + 'name': order_name(obj.name), + 'type': mimetypes.guess_type(obj.path)[0] or 'image/png', + 'thumbnailUrl': obj.url, + 'size': obj.size, + 'deleteUrl': reverse('upload-delete', args=[instance.pk]), + 'deleteType': 'DELETE', + } + + diff --git a/fileupload/urls.py b/fileupload/urls.py index bfdf903..06de8ec 100644 --- a/fileupload/urls.py +++ b/fileupload/urls.py @@ -1,3 +1,4 @@ +# encoding: utf-8 from django.conf.urls import patterns, url from fileupload.views import BasicVersionCreateView, BasicPlusVersionCreateView, PictureCreateView, AngularVersionCreateView, jQueryVersionCreateView, PictureDeleteView diff --git a/fileupload/views.py b/fileupload/views.py index 18a9dc8..2b06e79 100644 --- a/fileupload/views.py +++ b/fileupload/views.py @@ -1,86 +1,55 @@ -from fileupload.models import Picture -from django.views.generic import CreateView, DeleteView +# encoding: utf-8 +from django.views.generic import CreateView, DeleteView, View +from .models import Picture +from .response import JSONResponse, response_mimetype +from .serialize import serialize -from django.http import HttpResponse, HttpResponseRedirect -from django.utils import simplejson -from django.core.urlresolvers import reverse - -from django.conf import settings -import re - -def response_mimetype(request): - if "application/json" in request.META['HTTP_ACCEPT']: - return "application/json" - else: - return "text/plain" - -def orderName(name): - name = re.sub (r'^.*/', '', name) - if len(name)>20: - return name[:10] + "..." + name[-7:] - else: - return name class PictureCreateView(CreateView): model = Picture def form_valid(self, form): self.object = form.save() - f = self.request.FILES.get('file') - files = [{ - 'url': self.object.file.url, - 'name': orderName(f.name), - "type": "image/png", - 'thumbnailUrl': self.object.file.url, - 'size': f.size, - 'deleteUrl': reverse('upload-delete', args=[self.object.id]), - 'deleteType': "DELETE", - }] - data = {"files": files} - response = JSONResponse(data, {}, response_mimetype(self.request)) + files = [serialize(self.object)] + data = {'files': files} + response = JSONResponse(data, mimetype=response_mimetype(self.request)) response['Content-Disposition'] = 'inline; filename=files.json' return response + class BasicVersionCreateView(PictureCreateView): template_name_suffix = '_basic_form' + class BasicPlusVersionCreateView(PictureCreateView): template_name_suffix = '_basicplus_form' + class AngularVersionCreateView(PictureCreateView): template_name_suffix = '_angular_form' + class jQueryVersionCreateView(PictureCreateView): template_name_suffix = '_jquery_form' + class PictureDeleteView(DeleteView): model = Picture def delete(self, request, *args, **kwargs): self.object = self.get_object() self.object.delete() - response = JSONResponse(True, {}, response_mimetype(self.request)) + response = JSONResponse(True, mimetype=response_mimetype(request)) response['Content-Disposition'] = 'inline; filename=files.json' return response -def PictureListView(request): - files = [] - for obj in Picture.objects.all(): - files += [{ - 'name': orderName(obj.file.name), - 'size': obj.file.size, - 'url': obj.file.url, - 'thumbnailUrl': obj.file.url, - 'deleteUrl': reverse('upload-delete', args=[obj.id]), - 'deleteType': "DELETE" - }] - data = {"files": files} - response = JSONResponse(data, {}, response_mimetype(request)) - response['Content-Disposition'] = 'inline; filename=files.json' - return response - -class JSONResponse(HttpResponse): - """JSON response class.""" - def __init__(self,obj='',json_opts={},mimetype="application/json",*args,**kwargs): - content = simplejson.dumps(obj,**json_opts) - super(JSONResponse,self).__init__(content,mimetype,*args,**kwargs) + +class PictureListView(View): + def get(self, request, *args, **kwargs): + files = [] + for obj in Picture.objects.all(): + files.append(serialize(obj)) + data = {'files': files} + response = JSONResponse(data, mimetype=response_mimetype(request)) + response['Content-Disposition'] = 'inline; filename=files.json' + return response