Skip to content
This repository was archived by the owner on Nov 17, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
5e3c8bd
Fix (and add example for) using a Python function as a default value.
kkinder Mar 25, 2019
8a7bc2f
Enable testing of MongoEngine backend on Python 3
cjmayo Mar 25, 2020
3c122e2
Make pymongo backend testing PyMongo 3 compatible
cjmayo Mar 25, 2020
697271c
Don't attempt to collect pymongo test classes
cjmayo Mar 25, 2020
51057e1
typo fix
dvska May 8, 2020
44cfcac
fix secret typo
daniel-butler Jul 3, 2020
798e798
adding email validator
daniel-butler Jul 8, 2020
04c3bf7
Fix sqla.AdminModelConverter.convert_email empty string behavior
provinzkraut Aug 14, 2020
149bae2
Merge remote-tracking branch 'upstream/master' into bootstrap4
michaelbukachi Aug 27, 2020
e4097ea
fix: Correct styling issue in datepicker
michaelbukachi Aug 27, 2020
9c31b88
Fixed bs4 modal details view markup
TitaniumHocker Aug 30, 2020
d7493a8
fix: Correct styling for 'Cancel' button
michaelbukachi Aug 30, 2020
7287ed9
Fix bs4 edit modal
TitaniumHocker Aug 30, 2020
0604295
refactor: replace 'btn-danger' with 'btn-secondary'
michaelbukachi Aug 31, 2020
1c2a07e
Replace bootstrap3 well class with bootstrap4 card
rammie Sep 1, 2020
ebfb2ec
Merge pull request #2023 from michaelbukachi/bootstrap4
mrjoes Sep 4, 2020
2de7142
Update tools.py
jtbaker Sep 20, 2020
5e03c02
Add try/except handler for graceful import handler
jtbaker Sep 22, 2020
8d55b41
Merge pull request #2033 from jtbaker/feature/sqlalchemy-1.4-dep-upgrade
mrjoes Sep 22, 2020
192c6c6
Merge pull request #2026 from rammie/patch-1
mrjoes Sep 22, 2020
eb227fc
Merge pull request #2024 from TitaniumHocker/master
mrjoes Sep 22, 2020
e40eaf9
Merge pull request #1968 from cjmayo/mongoengine3
mrjoes Sep 22, 2020
e467190
fix: Fix bs4 popover
michaelbukachi Sep 28, 2020
58bf831
Merge pull request #2035 from michaelbukachi/master
mrjoes Sep 28, 2020
076b452
The `sudo` keyword is no longer supported
jugmac00 Oct 7, 2020
e764f6f
Merge pull request #2038 from jugmac00/patch-2
mrjoes Oct 9, 2020
1638c41
Dynamic sqlalchemy-utils version dependency
mrjoes Oct 26, 2020
becc783
WTForms 2.3.x test fixes
mrjoes Oct 26, 2020
7165a0a
Version bump
mrjoes Oct 26, 2020
ff12230
Minor fix to docs
krishraghuram Nov 6, 2020
78b27c4
Set correct Fileheaders when Uploading to S3
Bastian-Kuhn Nov 10, 2020
5fe3ce4
Merge pull request #2050 from Bastian-Kuhn/s3_fileheaders
mrjoes Nov 10, 2020
a70535b
Removed lowering the whole command in the rediscli.py
Bruising6802 Nov 25, 2020
bddefed
Merge pull request #2058 from Maciejfiedler/master
mrjoes Nov 25, 2020
43acc41
Merge pull request #2000 from daniel-butler/patch-2
mrjoes Nov 29, 2020
8638f8b
Pin mongoengine version to prevent syntax error on py35
greyli Dec 19, 2020
94dfa61
Add add_category method to flask_admin.Admin
okada-datasign Dec 22, 2020
62d35c9
Fix broken rendering when user specifies an endpoint other than 'admin'
justinvasel Jan 29, 2021
514fe35
Merge pull request #2082 from justinvasel/fix-rendering-for-custom-en…
mrjoes Jan 30, 2021
39bb6b1
minor changes
MahanteshR Feb 9, 2021
41b84b9
removed whitespace
MahanteshR Mar 6, 2021
8bd06d4
checks
MahanteshR Mar 6, 2021
f4a1a7b
Delete settings.json
MahanteshR Mar 6, 2021
5dfc30e
adding missing dependency on email_validator package
Mar 7, 2021
4ac0e16
Merge pull request #2094 from ondraz/example-auth-email-validator-dep…
alanhamlett Mar 17, 2021
7955768
Merge pull request #1982 from dvska/patch-1
alanhamlett Mar 17, 2021
9af9e95
Merge pull request #1999 from daniel-butler/patch-1
alanhamlett Mar 17, 2021
9441afa
Merge pull request #2049 from krishraghuram/patch-2
alanhamlett Mar 17, 2021
f099202
fix hybrid properties on nested models for sqlalchemy14
alexa-infra Mar 19, 2021
0a26895
fix test_advanced_joins unit-test
alexa-infra Mar 19, 2021
8588494
Merge pull request #2098 from alexa-infra/fix-sqlalchemy14
mrjoes Mar 19, 2021
d2588c1
Merge pull request #1834 from kkinder/master
mrjoes Mar 22, 2021
6e7460c
Update list.html
kanhebei Apr 7, 2021
5a525d0
Merge pull request #2103 from kanhebei/master
mrjoes Apr 7, 2021
57fe905
Update list.html
kanhebei Apr 12, 2021
c0117ce
Merge pull request #2104 from kanhebei/master
mrjoes Apr 12, 2021
0d4e65b
Update bs4_filters.js
julien66 Apr 13, 2021
903b3d3
Update form.js
julien66 Apr 13, 2021
c8877df
Version bump
mrjoes Apr 17, 2021
1fa727d
Add importing pass_context
a-was May 14, 2021
89a7eaa
Change contextfunction to pass_compat
a-was May 14, 2021
83b8d0e
Change Markup import
a-was May 15, 2021
b5f894d
Change escape import
a-was May 15, 2021
b4ebb11
Remove dependency on nose (port to pytest)
mcepl Jun 1, 2021
7f8a3c9
Make the code 2.7 syntax compatible.
mcepl Jun 1, 2021
25618dc
Fix CI
mcepl Jun 1, 2021
8c564cc
Fix a syntax error in tests/geoa/test_basic.py ... misplaced ends of …
mcepl Jun 1, 2021
b21e336
Upgrade jquery to 3.5.1
Jun 3, 2021
43ee2c0
Merge pull request #2110 from a-was/jinja3
mrjoes Jul 7, 2021
efbd258
Update bool_formatter for FA5
brandoningli Jul 30, 2021
feb0601
Add missing hyphen
brandoningli Jul 30, 2021
2cd4263
Use fas instead of deprecated fa
brandoningli Jul 30, 2021
5b9b0b8
Merge pull request #2131 from brandoningli/master
mrjoes Jul 30, 2021
00abc4d
Fix extra args missing in bootstrap4
cgaunet Jul 30, 2021
b760291
Fix `el is not defined` in x-editable-combodate popover handler
iburakov Jul 31, 2021
1597dc4
Merge pull request #2133 from iburakov/master
mrjoes Aug 3, 2021
fc2d62d
Merge pull request #2132 from cgaunet/fix-extra-args-missing-in-boots…
mrjoes Aug 3, 2021
efb9081
Merge pull request #2117 from rtilk89/jquery-3.5.1
mrjoes Aug 3, 2021
3377396
Merge pull request #2105 from julien66/bs4-filters-style
mrjoes Aug 3, 2021
e27e103
Merge pull request #2070 from greyli/fix-mongoengine-syntax-error-on-…
mrjoes Aug 3, 2021
08ac256
Merge pull request #2019 from provinzkraut/master
mrjoes Aug 3, 2021
ef737e4
Merge pull request #2085 from MahanteshR/admin
mrjoes Aug 3, 2021
e39f786
Merge pull request #2072 from okada-datasign/add_category
mrjoes Aug 3, 2021
9100f3f
Fix JSONField when the value is empty json
dangerousmanjay Aug 25, 2021
733cfac
fixes issue #2144 where X-editable combodate doesn't show up in Boots…
mccarthysean Sep 9, 2021
e7daac5
Merge branch 'master' into denose
mrjoes Oct 15, 2021
935c453
Merge pull request #2115 from mcepl/denose
mrjoes Oct 15, 2021
2f6d8f0
Merge pull request #2146 from mccarthysean/master
mrjoes Oct 15, 2021
8836362
Fixed editable column fields showing "Empty" bs4
caffeinatedMike Oct 16, 2021
07838bb
Merge pull request #2156 from caffeinatedMike/master
mrjoes Oct 16, 2021
c9ef5da
Updated upload fields to conditionally utilize new extra_filters argu…
caffeinatedMike Oct 18, 2021
20ff6c7
Removed float() left over from testing
caffeinatedMike Oct 18, 2021
ad78894
Merge pull request #2159 from caffeinatedMike/master
mrjoes Oct 18, 2021
d30a84e
Added additional check to is_editable
caffeinatedMike Oct 18, 2021
bf98268
Merge pull request #2161 from caffeinatedMike/master
mrjoes Oct 19, 2021
7b00465
Update JSONField to return empty dict
dangerousmanjay Oct 21, 2021
e81cb5d
Merge pull request #2139 from ojayyezzir/patch-1
mrjoes Oct 21, 2021
5f2b4d3
Add flask_debugtoolbar for peewee to flask-admin.
rammie Jul 15, 2019
a6d1356
Move debugtoolbar.
rammie Jul 15, 2019
553f62c
Update debugtoolbar.py
rammie Oct 31, 2019
ee6385a
Add flask_debugtoolbar for peewee to flask-admin.
rammie Jul 15, 2019
8623302
Move debugtoolbar.
rammie Jul 15, 2019
7c0df8f
Upgrade bootstrap4 icons to font awesome 5.
rammie Aug 26, 2020
c1bfb0e
Fix minor css issues and change default popover placement.
rammie Sep 1, 2020
6618d48
Merge branch 'master' into ram-merge-upstream-2
rammie Oct 23, 2021
8552be5
Fix bug where filters don't work.
rammie Oct 23, 2021
16b66df
Remove useless change.
rammie Oct 23, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
sudo: false
language: python
matrix:
include:
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ Or alternatively, you can download the repository and install manually by doing:

Tests
-----
Test are run with *nose*. If you are not familiar with this package you can get some more info from `their website <https://nose.readthedocs.io/>`_.
Test are run with *pytest*. If you are not familiar with this package you can get some more info from `their website <https://pytest.org/>`_.

To run the tests, from the project directory, simply::

pip install -r requirements-dev.txt
nosetests
pytest

You should see output similar to::

Expand Down
4 changes: 2 additions & 2 deletions doc/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,8 @@ This is minimal PyMongo view::

On top of that you can add sortable columns, filters, text search, etc.

For more, check the :class:`~flask_admin.contrib.pymongoe` API documentation. Or look at
the Peewee example at https://github.com/flask-admin/flask-admin/tree/master/examples/pymongo.
For more, check the :class:`~flask_admin.contrib.pymongo` API documentation. Or look at
the pymongo example at https://github.com/flask-admin/flask-admin/tree/master/examples/pymongo.

Migrating From Django
---------------------
Expand Down
13 changes: 13 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
Changelog
=========

1.5.8
-----

* SQLAlchemy 1.4.5+ compatibility fixes
* Redis CLI fixes

1.5.7
-----

* Bootstrap 4 support!
* Added hook for custom SQLAlchemy models initializers
* SQLAlchemy 1.4/2.0 compatibility fix

1.5.6
-----

Expand Down
2 changes: 1 addition & 1 deletion doc/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ details view** by setting::
can_view_details = True

**Removing columns** from the list view is easy, just pass a list of column names for
the *column_excludes_list* parameter::
the *column_exclude_list* parameter::

column_exclude_list = ['password', ]

Expand Down
2 changes: 1 addition & 1 deletion examples/auth-flask-login/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def index():
init_login()

# Create admin
admin = admin.Admin(app, 'Example: Auth', index_view=MyAdminIndexView(), base_template='my_master.html')
admin = admin.Admin(app, 'Example: Auth', index_view=MyAdminIndexView(), base_template='my_master.html', template_mode='bootstrap4')

# Add view
admin.add_view(MyModelView(User, db.session))
Expand Down
6 changes: 3 additions & 3 deletions examples/auth-flask-login/templates/admin/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ <h1>Flask-Admin example</h1>
<form method="POST" action="">
{{ form.hidden_tag() if form.hidden_tag }}
{% for f in form if f.type != 'CSRFTokenField' %}
<div>
{{ f.label }}
<div class="form-group">
{{ f.label }}<br>
{{ f }}
{% if f.errors %}
<ul>
Expand All @@ -28,7 +28,7 @@ <h1>Flask-Admin example</h1>
{% endif %}
</div>
{% endfor %}
<button class="btn" type="submit">Submit</button>
<button class="btn btn-primary" type="submit">Submit</button>
</form>
{{ link | safe }}
{% endif %}
Expand Down
13 changes: 7 additions & 6 deletions examples/auth-flask-login/templates/my_master.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

{% block access_control %}
{% if current_user.is_authenticated %}
<div class="btn-group pull-right">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<div class="dropdown show">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="icon-user"></i> {{ current_user.login }} <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('admin.logout_view') }}">Log out</a></li>
</ul>
</a>

<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<a class="btn" href="{{ url_for('admin.logout_view') }}">Log out</a>
</div>
</div>
{% endif %}
{% endblock %}
1 change: 1 addition & 0 deletions examples/auth/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ Flask
Flask-Admin
Flask-SQLAlchemy
Flask-Security>=1.7.5
email_validator
2 changes: 2 additions & 0 deletions examples/bootstrap4/app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import os
import os.path as op
from flask import Flask
Expand Down Expand Up @@ -27,6 +28,7 @@ class User(db.Model):
name = db.Column(db.Unicode(64))
email = db.Column(db.Unicode(64))
active = db.Column(db.Boolean, default=True)
created_at = db.Column(db.DateTime, default=datetime.datetime.now)

def __unicode__(self):
return self.name
Expand Down
6 changes: 4 additions & 2 deletions examples/peewee/app.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from flask import Flask
import uuid

import peewee
from flask import Flask

import flask_admin as admin
from flask_admin.contrib.peewee import ModelView


app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'

Expand Down Expand Up @@ -36,6 +36,7 @@ def __unicode__(self):


class Post(BaseModel):
id = peewee.UUIDField(primary_key=True, default=uuid.uuid4)
title = peewee.CharField(max_length=120)
text = peewee.TextField(null=False)
date = peewee.DateTimeField()
Expand Down Expand Up @@ -80,6 +81,7 @@ def index():

if __name__ == '__main__':
import logging

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)

Expand Down
2 changes: 1 addition & 1 deletion examples/sqla-custom-inline-forms/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# Create application
app = Flask(__name__)

# Create dummy secrey key so we can use sessions
# Create dummy secret key so we can use sessions
app.config['SECRET_KEY'] = '123456790'

# Create in-memory database
Expand Down
1 change: 1 addition & 0 deletions examples/sqla/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum34; python_version < '3.0'
sqlalchemy_utils
arrow
colour
email_validator

# note: for local development, replace 'Flask-Admin' above with a reference to
# your local copy of the repo e.g. '-e .' if you're installing this from the
Expand Down
2 changes: 1 addition & 1 deletion flask_admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '1.5.6'
__version__ = '1.5.8'
__author__ = 'Flask-Admin team'
__email__ = 'serge.koval+github@gmail.com'

Expand Down
5 changes: 5 additions & 0 deletions flask_admin/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,8 @@ def __new__(cls, name, this_bases, d):
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict

try:
from jinja2 import pass_context
except ImportError:
from jinja2 import contextfunction as pass_context
23 changes: 23 additions & 0 deletions flask_admin/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,29 @@ def add_views(self, *args):
for view in args:
self.add_view(view)

def add_category(self, name, class_name=None, icon_type=None, icon_value=None):
"""
Add a category of a given name

:param name:
The name of the new menu category.
:param class_name:
The class name for the new menu category.
:param icon_type:
The icon name for the new menu category.
:param icon_value:
The icon value for the new menu category.
"""
cat_text = as_unicode(name)

category = self.get_category_menu_item(name)
if category:
return

category = MenuCategory(name, class_name=class_name, icon_type=icon_type, icon_value=icon_value)
self._menu_categories[cat_text] = category
self._menu.append(category)

def add_sub_category(self, name, parent_name):

"""
Expand Down
5 changes: 4 additions & 1 deletion flask_admin/contrib/fileadmin/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ def send_file(self, file_path):

def save_file(self, path, file_data):
key = Key(self.bucket, path)
key.set_contents_from_file(file_data.stream)
headers = {
'Content-Type': file_data.content_type,
}
key.set_contents_from_file(file_data.stream, headers=headers)

def delete_tree(self, directory):
self._check_empty_directory(directory)
Expand Down
2 changes: 1 addition & 1 deletion flask_admin/contrib/geoa/typefmt.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from flask_admin.contrib.sqla.typefmt import DEFAULT_FORMATTERS as BASE_FORMATTERS
from jinja2 import Markup
from markupsafe import Markup
from wtforms.widgets import html_params
from geoalchemy2.shape import to_shape
from geoalchemy2.elements import WKBElement
Expand Down
2 changes: 1 addition & 1 deletion flask_admin/contrib/mongoengine/typefmt.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from jinja2 import Markup, escape
from markupsafe import Markup, escape

from mongoengine.base import BaseList
from mongoengine.fields import GridFSProxy, ImageGridFsProxy
Expand Down
2 changes: 1 addition & 1 deletion flask_admin/contrib/mongoengine/widgets.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from wtforms.widgets import html_params

from jinja2 import escape
from markupsafe import escape

from mongoengine.fields import GridFSProxy, ImageGridFsProxy

Expand Down
2 changes: 1 addition & 1 deletion flask_admin/contrib/peewee/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ def create_model(self, form):
model = self.model()
form.populate_obj(model)
self._on_model_change(form, model, True)
model.save()
model.save(force_insert=True)

# For peewee have to save inline forms after model was saved
save_inline(form, model)
Expand Down
4 changes: 2 additions & 2 deletions flask_admin/contrib/rediscli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from flask import request

from jinja2 import Markup
from markupsafe import Markup

from flask_admin.base import BaseView, expose
from flask_admin.babel import gettext
Expand Down Expand Up @@ -196,7 +196,7 @@ def execute_view(self):
AJAX API.
"""
try:
cmd = request.form.get('cmd').lower()
cmd = request.form.get('cmd')
if not cmd:
return self._error('Cli: Empty command.')

Expand Down
6 changes: 5 additions & 1 deletion flask_admin/contrib/sqla/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,11 @@ def convert_arrow_time(self, field_args, **extra):
return form.DateTimeField(**field_args)

@converts('sqlalchemy_utils.types.email.EmailType')
def convert_email(self, field_args, **extra):
def convert_email(self, field_args, column=None, **extra):
if column.nullable:
filters = field_args.get('filters', [])
filters.append(lambda x: x or None)
field_args['filters'] = filters
field_args['validators'].append(validators.Email())
return fields.StringField(**field_args)

Expand Down
11 changes: 9 additions & 2 deletions flask_admin/contrib/sqla/tools.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import types

from sqlalchemy import tuple_, or_, and_, inspect
from sqlalchemy.ext.declarative.clsregistry import _class_resolver
try:
# Attempt _class_resolver import from SQLALchemy 1.4/2.0 module architecture.
from sqlalchemy.orm.clsregistry import _class_resolver
except ImportError:
# If 1.4/2.0 module import fails, fall back to <1.3.x architecture.
from sqlalchemy.ext.declarative.clsregistry import _class_resolver
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.ext.associationproxy import ASSOCIATION_PROXY
from sqlalchemy.sql.operators import eq
Expand Down Expand Up @@ -201,7 +206,9 @@ def is_hybrid_property(model, attr_name):
if is_association_proxy(attr):
attr = attr.remote_attr
last_model = attr.property.argument
if isinstance(last_model, _class_resolver):
if isinstance(last_model, string_types):
last_model = attr.property._clsregistry_resolve_name(last_model)()
elif isinstance(last_model, _class_resolver):
last_model = model._decl_class_registry[last_model.arg]
elif isinstance(last_model, (types.FunctionType, types.MethodType)):
last_model = last_model()
Expand Down
2 changes: 1 addition & 1 deletion flask_admin/form/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def _value(self):
# prevent utf8 characters from being converted to ascii
return as_unicode(json.dumps(self.data, ensure_ascii=False))
else:
return ''
return '{}'

def process_formdata(self, valuelist):
if valuelist:
Expand Down
2 changes: 1 addition & 1 deletion flask_admin/form/rules.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from jinja2 import Markup
from markupsafe import Markup

from flask_admin._compat import string_types
from flask_admin import helpers
Expand Down
12 changes: 9 additions & 3 deletions flask_admin/form/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage

from wtforms import ValidationError, fields
from wtforms import ValidationError, fields, __version__ as wtforms_version
from wtforms.widgets import html_params

try:
Expand Down Expand Up @@ -186,6 +186,9 @@ class MyForm(BaseForm):

self._should_delete = False

if int(wtforms_version[0]) < 3:
kwargs.pop('extra_filters', None)

super(FileUploadField, self).__init__(label, validators, **kwargs)

def is_file_allowed(self, filename):
Expand Down Expand Up @@ -216,13 +219,16 @@ def pre_validate(self, form):
if not self._allow_overwrite 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):
def process(self, formdata, data=unset_value, extra_filters=None):
if formdata:
marker = '_%s-delete' % self.name
if marker in formdata:
self._should_delete = True

return super(FileUploadField, self).process(formdata, data)
if int(wtforms_version[0]) < 3:
return super(FileUploadField, self).process(formdata, data)
else:
return super(FileUploadField, self).process(formdata, data, extra_filters) # noqa

def process_formdata(self, valuelist):
if self._should_delete:
Expand Down
5 changes: 2 additions & 3 deletions flask_admin/helpers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from re import sub, compile
from jinja2 import contextfunction
from flask import g, request, url_for, flash
from wtforms.validators import DataRequired, InputRequired

from flask_admin._compat import urljoin, urlparse, iteritems
from flask_admin._compat import iteritems, pass_context, urljoin, urlparse

from ._compat import string_types

Expand Down Expand Up @@ -109,7 +108,7 @@ def flash_errors(form, message):
flash(gettext(message, error=str(errors)), 'error')


@contextfunction
@pass_context
def resolve_ctx(context):
"""
Resolve current Jinja2 context and store it for general consumption.
Expand Down
Loading