Commit 868f805e authored by Okhin's avatar Okhin
Browse files

Fixing the multifile upload part

parent 0332e33d
......@@ -6,30 +6,23 @@ Released into the Public Domain
"""
from django.utils.encoding import force_unicode
from django.utils.datastructures import MultiValueDict
from django.utils.datastructures import MultiValueDict, MergeDict
from django.utils.translation import ugettext
from django.forms.fields import Field, EMPTY_VALUES
from django.core.files.uploadedfile import UploadedFile
from django.forms.widgets import FileInput
from django.forms.widgets import Input, FILE_INPUT_CONTRADICTION
from django.forms.util import ErrorList, ValidationError, flatatt
from django.utils.safestring import mark_safe
class MultiFileInput(FileInput):
FILE_INPUT_EMPTY_VALUE = object()
class MultiFileInput(Input):
"""
A widget to be used by the MultiFileField to allow the user to upload
multiple files at one time.
"""
def __init__(self, attrs=None, *args, **kwargs):
"""
Create a MultiFileInput.
The 'count' attribute can be specified to default the number of
file boxes initially presented.
"""
super(MultiFileInput, self).__init__(attrs, *args, **kwargs)
self.attrs = {'count':1}
if attrs:
self.attrs.update(attrs)
input_type = 'file'
needs_multipart_form = True
def render(self, name, value, attrs=None):
"""
......@@ -37,56 +30,23 @@ class MultiFileInput(FileInput):
Should not be overridden. Instead, subclasses should override the
js, link, and/or fields methods which provide content to this method.
"""
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name+'[]')
count = final_attrs['count']
if count<1: count=1
del final_attrs['count']
if attrs is None:
attrs = {}
js = self.js(name, value, count, final_attrs)
link = self.link(name, value, count, final_attrs)
fields = self.fields(name, value, count, final_attrs)
name += '[]'
attrs['multiple'] = 'multiple'
return mark_safe(js+link+fields)
def fields(self, name, value, count, attrs=None):
"""
Renders the necessary number of file input boxes.
"""
return u''.join([u'<input class="attachments"%s />\n' % flatatt(dict(attrs, id=attrs['id']+str(i))) for i in range(count)])
def link(self, name, value, count, attrs=None):
"""
Renders a link to add more file input boxes.
"""
return u"<div><a id='add_attach' onclick=\"javascript:new_%(name)s()\">Add more attachments</a></div>" % {'name':name}
def js(self, name, value, count, attrs=None):
"""
Renders a bit of Javascript to add more file input boxes.
"""
return u"""
<script>
<!--
%(id)s_counter=%(count)d;
function new_%(name)s() {
b=document.getElementById('%(id)s0');
c=b.cloneNode(false);
c.id='%(id)s'+(%(id)s_counter++);
b.parentNode.insertBefore(c,b);
}
-->
</script>
""" % {'id':attrs['id'], 'name':name, 'count':count}
return super(MultiFileInput, self).render(name, None, attrs=attrs)
def value_from_datadict(self, data, files, name):
"""
File widgets take data from FILES, not POST.
File widget takes data from FILES, not POST
we need to add [] for w3c recoomendation
"""
name = name+'[]'
if isinstance(files, MultiValueDict):
name += '[]'
if isinstance(files, (MultiValueDict, MergeDict)):
return files.getlist(name)
else:
return None
return files.get(name, None)
def id_for_label(self, id_):
"""
......@@ -102,56 +62,37 @@ class MultiFileField(Field):
A field allowing users to upload multiple files at once.
"""
widget = MultiFileInput
count = 1
max_length = None
allow_empty_file = None
def __init__(self, count=1, strict=False, *args, **kwargs):
"""
strict is whether the number of files uploaded must equal count
"""
self.count = count
self.strict = strict
super(MultiFileField, self).__init__(*args, **kwargs)
def widget_attrs(self, widget):
"""
Adds the count to the MultiFileInput widget.
"""
if isinstance(widget, MultiFileInput):
return {'count':self.count}
return {}
def clean(self, data):
def to_python(self, data):
"""
Cleans the data and makes sure that all the files had some content.
Also checks whether a file was required.
"""
super(MultiFileField, self).clean(data)
if not self.required and data in EMPTY_VALUES:
if data in EMPTY_VALUES:
return None
try:
f = map(lambda a: UploadedFile(a['filename'], a['content']), data)
except TypeError:
raise ValidationError(ugettext(u"No file was submitted. Check the encoding type on the form."))
except KeyError:
raise ValidationError(ugettext(u"No file was submitted."))
if data is FILE_INPUT_EMPTY_VALUE:
raise validationError(self.Error_messages['empty_multiply'])
for a_file in f:
if not a_file.content:
raise ValidationError(ugettext(u"The submitted file is empty."))
if self.strict and len(f) != self.count:
raise ValidationError(ugettext(u"An incorrect number of files were uploaded."))
return f
class FixedMultiFileInput(MultiFileInput):
"""
A MultiFileInput widget that doesn't print the javascript code to allow
the user to add more file input boxes.
"""
def link(self, name, value, count, attrs=None):
return u''
def js(self, name, value, count, attrs=None):
return u''
# UploadedFile objects should have name and size attributes
for d in data:
try:
file_name = d.name
file_size = d.size
except AttributeError:
raise ValidationError(self.Error_messages['invalid'])
if self.max_length is not None and file_size > self.max_length:
error_values = {'max': self.max_length, 'length': file_size}
raise ValidationError(self.error_messages['max_length'] % error_values)
if not file_name:
raise ValidationError(self.error_messages['invalid'])
if not self.allow_empty_file and not file_size:
raise ValidationError(self.Error_messages['empty'])
return data
def bound_data(self, data, initial):
if data in (None, FILE_INPUT_EMPTY_VALUE, FILE_INPUT_CONTRADICTION):
return initial
return data
......@@ -192,15 +192,6 @@ class AddForm(FormView):
messages.add_message(self.request, messages.INFO, _('Thank you for submitting this report, you will receive a verification email immediately, if not check your spam folder.'))
return super(AddForm, self).form_valid(form)
def post(self, request, *args, **kwargs):
# We needto do special work with the form view
form = self.form_class(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect(self.success_url)
else:
return render(request, self.template_name, {'form': form})
def get_context_data(self, **kwargs):
context = super(AddForm, self).get_context_data(**kwargs)
reports = sorted([(i['total'],i['id'])
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment