Skip to content

Commit

Permalink
Merge branch 'master' of github.com:flask-admin/flask-admin
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjoes committed Jun 13, 2015
2 parents c62a171 + 38173f8 commit 6b6fe51
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
3 changes: 2 additions & 1 deletion examples/forms/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class FileView(sqla.ModelView):
form_args = {
'path': {
'label': 'File',
'base_path': file_path
'base_path': file_path,
'allow_overwrite': False
}
}

Expand Down
27 changes: 25 additions & 2 deletions flask_admin/form/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,21 @@ def __call__(self, field, **kwargs):

template = self.data_template if field.data else self.empty_template

if field.errors:
template = self.empty_template

if field.data and isinstance(field.data, FileStorage):
value = field.data.filename
else:
value = field.data or ''

return HTMLString(template % {
'text': html_params(type='text',
readonly='readonly',
value=field.data,
value=value,
name=field.name),
'file': html_params(type='file',
value=value,
**kwargs),
'marker': '_%s-delete' % field.name
})
Expand Down Expand Up @@ -122,7 +131,7 @@ class FileUploadField(fields.StringField):
def __init__(self, label=None, validators=None,
base_path=None, relative_path=None,
namegen=None, allowed_extensions=None,
permission=0o666,
permission=0o666, allow_overwrite=True,
**kwargs):
"""
Constructor.
Expand Down Expand Up @@ -154,13 +163,19 @@ class MyForm(BaseForm):
:param allowed_extensions:
List of allowed extensions. If not provided, will allow any file.
:param allow_overwrite:
Whether to overwrite existing files in upload directory. Defaults to `True`.
.. versionadded:: 1.1.1
The `allow_overwrite` parameter was added.
"""
self.base_path = base_path
self.relative_path = relative_path

self.namegen = namegen or namegen_filename
self.allowed_extensions = allowed_extensions
self.permission = permission
self._allow_overwrite = allow_overwrite

self._should_delete = False

Expand Down Expand Up @@ -188,6 +203,11 @@ def _is_uploaded_file(self, data):
def pre_validate(self, form):
if self._is_uploaded_file(self.data) and not self.is_file_allowed(self.data.filename):
raise ValidationError(gettext('Invalid file extension'))
# Handle overwriting existing content
if not self._is_uploaded_file(self.data):
return
if self._allow_overwrite == False and os.path.exists(self._get_path(self.data.filename)):
raise ValidationError(gettext('File "%s" already exists.' % self.data.filename))

def process(self, formdata, data=unset_value):
if formdata:
Expand Down Expand Up @@ -253,6 +273,9 @@ def _save_file(self, data, filename):
if not op.exists(op.dirname(path)):
os.makedirs(os.path.dirname(path), self.permission | 0o111)

if self._allow_overwrite == False and os.path.exists(path):
raise ValueError(gettext('File "%s" already exists.' % path))

data.save(path)

return filename
Expand Down
22 changes: 22 additions & 0 deletions flask_admin/tests/test_form_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ def _remove_testfiles():
class TestForm(form.BaseForm):
upload = form.FileUploadField('Upload', base_path=path)

class TestNoOverWriteForm(form.BaseForm):
upload = form.FileUploadField('Upload', base_path=path, allow_overwrite=False)

class Dummy(object):
pass

Expand Down Expand Up @@ -74,6 +77,7 @@ class Dummy(object):

# Check delete
with app.test_request_context(method='POST', data={'_upload-delete': 'checked'}):

my_form = TestForm(helpers.get_form_data())

ok_(my_form.validate())
Expand All @@ -83,6 +87,24 @@ class Dummy(object):

ok_(not op.exists(op.join(path, 'test2.txt')))

# Check overwrite
_remove_testfiles()
my_form_ow = TestNoOverWriteForm()
with app.test_request_context(method='POST', data={'upload': (BytesIO(b'Hullo'), 'test1.txt')}):
my_form_ow = TestNoOverWriteForm(helpers.get_form_data())

ok_(my_form_ow.validate())
my_form_ow.populate_obj(dummy)
eq_(dummy.upload, 'test1.txt')
ok_(op.exists(op.join(path, 'test1.txt')))

with app.test_request_context(method='POST', data={'upload': (BytesIO(b'Hullo'), 'test1.txt')}):
my_form_ow = TestNoOverWriteForm(helpers.get_form_data())

ok_(not my_form_ow.validate())

_remove_testfiles()


def test_image_upload_field():
app = Flask(__name__)
Expand Down

0 comments on commit 6b6fe51

Please sign in to comment.