Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
La Quadrature du Net
Respect My Net
Commits
868f805e
Commit
868f805e
authored
Mar 08, 2016
by
Okhin
Browse files
Fixing the multifile upload part
parent
0332e33d
Changes
2
Show whitespace changes
Inline
Side-by-side
bt/multifile.py
View file @
868f805e
...
...
@@ -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
File
Input
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
bt/views.py
View file @
868f805e
...
...
@@ -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'
])
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment