Skip to content

Commit

Permalink
drag and drop uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
timbroder committed Sep 6, 2012
1 parent c2b6db6 commit ca23182
Show file tree
Hide file tree
Showing 24 changed files with 2,676 additions and 96 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ static/bocci/images
static/bocci/images/mike.eggs_jpg_100x100_q85.jpg
static/upload/*
myenv*
*project
*projectmyenv
2 changes: 2 additions & 0 deletions stager/multiuploader/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VERSION = (1, 2, 1)
__version__ = '.'.join(map(str, VERSION))
9 changes: 9 additions & 0 deletions stager/multiuploader/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from models import MultiuploaderImage
from django.contrib import admin

class MultiuploaderImageAdmin(admin.ModelAdmin):
search_fields = ["filename", "key_data"]
list_display = ["filename", "image", "key_data"]
list_filter = ["filename", "image", "key_data"]

admin.site.register(MultiuploaderImage, MultiuploaderImageAdmin)
29 changes: 29 additions & 0 deletions stager/multiuploader/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from django.db import models
import random

from django.conf import settings
try:
storage = settings.MULTI_IMAGES_FOLDER+'/'
except AttributeError:
storage = 'multiuploader_images/'

class MultiuploaderImage(models.Model):
"""Model for storing uploaded photos"""
filename = models.CharField(max_length=60, blank=True, null=True)
image = models.FileField(upload_to=storage)
key_data = models.CharField(max_length=90, unique=True, blank=True, null=True)
upload_date = models.DateTimeField(auto_now_add=True)

@property
def key_generate(self):
"""returns a string based unique key with length 80 chars"""
while 1:
key = str(random.getrandbits(256))
try:
MultiuploaderImage.objects.get(key=key)
except:
return key

def __unicode__(self):
return self.image.name

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{% load verbatim %}
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/base/jquery-ui.css" id="theme">
<link rel="stylesheet" href="{{ static_url }}multiuploader/styles/jquery.fileupload-ui.css">
<div id="fileupload" data-action="{% url multi %}">
<div class="fileupload-buttonbar">
<button type="submit" class="start">Start upload</button>
<button type="reset" class="cancel">Cancel upload</button>
</div>
<div class="fileupload-content">
<table class="files"></table>
<div class="fileupload-progressbar"></div>
</div>
</div>
<div id="help" style="color:gray;">
<h2>
<p>You can select Multiple files at once using Ctrl(Win) or Command(Mac), or you can drag'n'drop your files on this form.</p>
</h2>
</div>
{% verbatim %}
<script id="template-upload" type="text/x-jquery-tmpl">
<tr class="template-upload{{if error}} ui-state-error{{/if}}">
<td class="preview"></td>
<td class="name">${name}</td>
<td class="size">${sizef}</td>
{{if error}}
<td class="error" colspan="2">Error:
{{if error === 'maxFileSize'}}File is too big
{{else error === 'minFileSize'}}File is too small
{{else error === 'acceptFileTypes'}}Filetype not allowed
{{else error === 'maxNumberOfFiles'}}Max number of files exceeded
{{else}}${error}
{{/if}}
</td>
{{else}}
<td class="progress"><div></div></td>
<td class="start"><button style="visibility:hidden">Start</button></td>
{{/if}}
<td class="cancel"><button>Cancel</button></td>
</tr>
</script>
<script id="template-download" type="text/x-jquery-tmpl">
<tr class="template-download{{if error}} ui-state-error{{/if}}">
{{if error}}
<td></td>
<td class="name">${name}</td>
<td class="size">${sizef}</td>
<td class="error" colspan="2">Error:
{{if error === 1}}File exceeds upload_max_filesize (php.ini directive)
{{else error === 2}}File exceeds MAX_FILE_SIZE (HTML form directive)
{{else error === 3}}File was only partially uploaded
{{else error === 4}}No File was uploaded
{{else error === 5}}Missing a temporary folder
{{else error === 6}}Failed to write file to disk
{{else error === 7}}File upload stopped by extension
{{else error === 'maxFileSize'}}File is too big
{{else error === 'minFileSize'}}File is too small
{{else error === 'acceptFileTypes'}}Filetype not allowed
{{else error === 'maxNumberOfFiles'}}Max number of files exceeded
{{else error === 'uploadedBytes'}}Uploaded bytes exceed file size
{{else error === 'emptyResult'}}Empty file upload result
{{else}}${error}
{{/if}}
</td>
{{else}}
<td class="preview">
{{if thumbnail_url}}
<a href="${url}" target="_blank"><img src="${thumbnail_url}"></a>
{{/if}}
</td>
<td class="name">
<a href="${url}"{{if thumbnail_url}} target="_blank"{{/if}}>${name}</a>
</td>
<td class="size">${sizef}</td>
<td colspan="2"></td>
{{/if}}
</tr>
</script>
{% endverbatim %}
<script src="/media/grappelli/jquery/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="/media/grappelli/jquery/ui/js/jquery-ui-1.8.18.custom.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
<script src="{{ static_url }}multiuploader/scripts/jquery.iframe-transport.js"></script>
<script src="{{ static_url }}multiuploader/scripts/jquery.fileupload.js"></script>
<script src="{{ static_url }}multiuploader/scripts/jquery.fileupload-ui.js"></script>
<script src="{{ static_url }}multiuploader/scripts/application.js"></script>
<script type="text/javascript" src="{{ static_url }}js/jquery.colorPicker.js"></script>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<img src="{{ multi_single_url }}">
Empty file.
8 changes: 8 additions & 0 deletions stager/multiuploader/templatetags/multiuploader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django import template
from django.conf import settings

register = template.Library()

@register.inclusion_tag('multiuploader/multiuploader_main.html')
def multiupform():
return {'static_url':settings.MEDIA_URL,}
44 changes: 44 additions & 0 deletions stager/multiuploader/templatetags/verbatim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
jQuery templates use constructs like:
{{if condition}} print something{{/if}}
This, of course, completely screws up Django templates,
because Django thinks {{ and }} mean something.
Wrap {% verbatim %} and {% endverbatim %} around those
blocks of jQuery templates and this will try its best
to output the contents with no changes.
"""

from django import template

register = template.Library()


class VerbatimNode(template.Node):

def __init__(self, text):
self.text = text

def render(self, context):
return self.text


@register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))
23 changes: 23 additions & 0 deletions stager/multiuploader/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""

from django.test import TestCase

class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)

__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

18 changes: 18 additions & 0 deletions stager/multiuploader/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.conf.urls.defaults import *
from django.conf import settings

try:
delete_url = settings.MULTI_FILE_DELETE_URL
except AttributeError:
delete_url = 'multi_delete'

try:
image_url = settings.MULTI_IMAGE_URL
except AttributeError:
image_url = 'multi_image'

urlpatterns = patterns('',
(r'^'+delete_url+'/(\d+)/$', 'multiuploader.views.multiuploader_delete'),
url(r'^multi/$', 'multiuploader.views.multiuploader', name='multi'),
(r'^'+image_url+'/(\d+)/$', 'multiuploader.views.multi_show_uploaded'),
)
152 changes: 152 additions & 0 deletions stager/multiuploader/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
from django.shortcuts import get_object_or_404, render_to_response
from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest
from models import MultiuploaderImage
from django.core.files.uploadedfile import UploadedFile
from staging.models import CompSlide, Comp
from django.forms.models import inlineformset_factory
from django.template import loader, Context
from django.contrib.admin import widgets, helpers
from stager.staging.admin import CompSlideInline
from stager.staging.forms import *

#importing json parser to generate jQuery plugin friendly json response
from django.utils import simplejson

#for generating thumbnails
#sorl-thumbnails must be installed and properly configured
from sorl.thumbnail import get_thumbnail


from django.views.decorators.csrf import csrf_exempt

import logging
log = logging

@csrf_exempt
def multiuploader_delete(request, pk):
"""
View for deleting photos with multiuploader AJAX plugin.
made from api on:
https://github.com/blueimp/jQuery-File-Upload
"""
if request.method == 'POST':
log.info('Called delete image. image id='+str(pk))
image = get_object_or_404(MultiuploaderImage, pk=pk)
image.delete()
log.info('DONE. Deleted photo id='+str(pk))
return HttpResponse(str(pk))
else:
log.info('Received not POST request to delete image view')
return HttpResponseBadRequest('Only POST accepted')

@csrf_exempt
def multiuploader(request):
"""
Main Multiuploader module.
Parses data from jQuery plugin and makes database changes.
"""
if request.method == 'POST':
print "HIIIII"
comp_id = request.POST.get('compId', None)
print comp_id
try:
print comp_id
comp = Comp.objects.get(id=comp_id)
except:
return HttpResponseBadRequest('Comp Does Not Exist')
log.info('received POST to main multiuploader view')
if request.FILES == None:
return HttpResponseBadRequest('Must have files attached!')

#getting file data for farther manipulations
file = request.FILES[u'files[]']

wrapped_file = UploadedFile(file)
filename = wrapped_file.name
file_size = wrapped_file.file.size

slide = CompSlide()
slide.title = filename
slide.image = file
slide.comp = comp
slide.name = "NAME"
slide.save()

log.info ('Got file: "%s"' % str(filename))
log.info('Content type: "$s" % file.content_type')




#writing file manually into model
#because we don't need form of any type.
image = MultiuploaderImage()
image.filename=str(filename)
image.image=file
image.key_data = image.key_generate
#image.save()
log.info('File saving done')

#getting thumbnail url using sorl-thumbnail
#if 'image' in file.content_type.lower():
# im = get_thumbnail(image, "80x80", quality=50)
# thumb_url = im.url
#else:
thumb_url = ''

#settings imports
try:
file_delete_url = settings.MULTI_FILE_DELETE_URL+'/'
file_url = settings.MULTI_IMAGE_URL+'/'+image.key_data+'/'
except AttributeError:
file_delete_url = 'multi_delete/'
file_url = 'multi_image/'+image.key_data+'/'
slide_fields = ('name','image','alignment','backgroundfield', 'remove_background', 'background_colorfield', 'active', 'ordering')
InlineAdminFormSetFactory = inlineformset_factory(Comp, CompSlide, extra=0, can_order=True, can_delete=True, fields=slide_fields)
inline_admin_formset = InlineAdminFormSetFactory(instance=comp)
#inline_admin_formset.opts.sortable_field_name = "ordering"
"""from django.contrib import admin
admin_site = admin.site
inline = CompSlideInline(Comp, admin_site)
prefix = FormSet.get_default_prefix()
formset = FormSet(instance=self.model(), prefix=prefix,
queryset=inline.queryset(request))
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
fieldsets, prepopulated, readonly, model_admin=self)
"""
#print inline_admin_formset
#print "%s" % inline_admin_formset
t = loader.get_template('admin/staging/edit_inline/_comp_slide_drag_upload_ajax.html')
c = Context({ 'inline_admin_formset': inline_admin_formset, 'slide_fields': slide_fields })
rendered = t.render(c)
# print rendered
print 'got rendered?'

#generating json response array
result = []
result.append({"name":filename,
"size":file_size,
"url":file_url,
"thumbnail_url":thumb_url,
#"delete_url":file_delete_url+str(image.pk)+'/',
"delete_type":"POST",
"html": rendered })
response_data = simplejson.dumps(result)

#checking for json data type
#big thanks to Guy Shapiro
if "application/json" in request.META['HTTP_ACCEPT_ENCODING']:
mimetype = 'application/json'
else:
mimetype = 'text/plain'
return HttpResponse(response_data, mimetype=mimetype)
else: #GET
return HttpResponse('Only POST accepted')

def multi_show_uploaded(request, key):
"""Simple file view helper.
Used to show uploaded file directly"""
image = get_object_or_404(MultiuploaderImage, key_data=key)
url = settings.MEDIA_URL+image.image.name
return render_to_response('multiuploader/one_image.html', {"multi_single_url":url,})
Loading

0 comments on commit ca23182

Please sign in to comment.