Skip to content

Commit 8ef0df5

Browse files
committed
Initial Commit & Release (0.1)
Thanks to http://koensblog.eu/blog/7/multiple-file-upload-django for inspiration
0 parents  commit 8ef0df5

7 files changed

Lines changed: 186 additions & 0 deletions

File tree

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
*.py[cod]
2+
3+
# C extensions
4+
*.so
5+
6+
# Packages
7+
*.egg
8+
*.egg-info
9+
dist
10+
build
11+
eggs
12+
parts
13+
bin
14+
var
15+
sdist
16+
develop-eggs
17+
.installed.cfg
18+
lib
19+
lib64
20+
__pycache__
21+
22+
# Installer logs
23+
pip-log.txt
24+
25+
# Unit test / coverage reports
26+
.coverage
27+
.tox
28+
nosetests.xml
29+
30+
# Translations
31+
*.mo
32+
33+
# Mr Developer
34+
.mr.developer.cfg
35+
.project
36+
.pydevproject
37+
38+
env/

LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2014 Chive - Kim Thoenen (kim@smuzey.ch)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include LICENSE.txt
2+
recursive-exclude * *.pyc

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Django Multiupload
2+
3+
Simple drop-in multi file upload field for django forms using HTML5's ``multiple`` attribute.
4+
5+
## Installation
6+
7+
* Install the package using pip (or easy_install if you really have to)
8+
9+
```sh
10+
$ pip install django-multiupload
11+
```
12+
13+
* .. or directly from this repository the get the development version (if you're feeling adventurous)
14+
15+
```sh
16+
$ pip install -e git+https://github.com/Chive/django-multiupload.git#egg=multiupload
17+
```
18+
19+
## Usage
20+
21+
* Add the form field to your form and make sure to save the uploaded files in the form's ``save`` method
22+
23+
```python
24+
from multiupload.fields import MultiFileField
25+
26+
27+
class MyUploadForm(forms.Form):
28+
attachments = MultiFileField(max_num=3, min_num=1, max_file_size=1024*1024*5)
29+
...
30+
31+
def save(self, commit=True):
32+
super(MyUploadForm, self).save(commit=commit)
33+
34+
for each in self.cleaned_data['attachments']:
35+
att = Attachment(parent=self.instance, file=each)
36+
att.save()
37+
38+
return self.instance
39+
```

multiupload/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# -*- coding: utf-8 -*-
2+
__version__ = '0.1'

multiupload/fields.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# -*- coding: utf-8 -*-
2+
from django import forms
3+
from django.core.exceptions import ValidationError
4+
from django.utils.translation import ugettext_lazy as _
5+
6+
7+
class MultiFileInput(forms.FileInput):
8+
def render(self, name, value, attrs=None):
9+
attrs['multiple'] = 'multiple'
10+
return super(MultiFileInput, self).render(name, value, attrs)
11+
12+
def value_from_datadict(self, data, files, name):
13+
if hasattr(files, 'getlist'):
14+
return files.getlist(name)
15+
else:
16+
return [files.get(name)]
17+
18+
19+
class MultiFileField(forms.FileField):
20+
widget = MultiFileInput
21+
default_error_messages = {
22+
'min_num': _(u'Ensure at least %(min_num)s files are uploaded (received %(num_files)s).'),
23+
'max_num': _(u'Ensure at most %(max_num)s files are uploaded (received %(num_files)s).'),
24+
'file_size': _(u'File %(uploaded_file_name)s exceeded maximum upload size.'),
25+
}
26+
27+
def __init__(self, *args, **kwargs):
28+
self.min_num = kwargs.pop('min_num', 0)
29+
self.max_num = kwargs.pop('max_num', None)
30+
self.maximum_file_size = kwargs.pop('max_file_size', None)
31+
super(MultiFileField, self).__init__(*args, **kwargs)
32+
33+
def to_python(self, data):
34+
ret = []
35+
for item in data:
36+
ret.append(super(MultiFileField, self).to_python(item))
37+
return ret
38+
39+
def validate(self, data):
40+
super(MultiFileField, self).validate(data)
41+
num_files = len(data)
42+
if len(data) and not data[0]:
43+
num_files = 0
44+
if num_files < self.min_num:
45+
raise ValidationError(self.error_messages['min_num'] % {'min_num': self.min_num, 'num_files': num_files})
46+
elif self.max_num and num_files > self.max_num:
47+
raise ValidationError(self.error_messages['max_num'] % {'max_num': self.max_num, 'num_files': num_files})
48+
for uploaded_file in data:
49+
if uploaded_file.size > self.maximum_file_size:
50+
raise ValidationError(self.error_messages['file_size'] % { 'uploaded_file_name': uploaded_file.name})

setup.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# -*- coding: utf-8 -*-
2+
from setuptools import setup, find_packages
3+
from multiupload import __version__
4+
5+
REQUIREMENTS = []
6+
7+
CLASSIFIERS = [
8+
'Development Status :: 4 - Beta',
9+
'Environment :: Web Environment',
10+
'Framework :: Django',
11+
'Intended Audience :: Developers',
12+
'License :: OSI Approved :: BSD License',
13+
'Operating System :: OS Independent',
14+
'Programming Language :: Python',
15+
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
16+
'Topic :: Software Development',
17+
'Topic :: Software Development :: Libraries :: Application Frameworks',
18+
]
19+
20+
setup(
21+
name='django-multiupload',
22+
version=__version__,
23+
description='A short description of the app.',
24+
author='Chive',
25+
author_email='kim@smuzey.ch',
26+
url='https://github.com/Chive/django-multiupload',
27+
packages=find_packages(),
28+
license='LICENSE.txt',
29+
platforms=['OS Independent'],
30+
install_requires=REQUIREMENTS,
31+
classifiers=CLASSIFIERS,
32+
include_package_data=True,
33+
zip_safe=False
34+
)

0 commit comments

Comments
 (0)