flask-appbuilder 3.2.1rc1__py3-none-any.whl → 5.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flask_appbuilder/__init__.py +2 -3
- flask_appbuilder/_compat.py +0 -1
- flask_appbuilder/actions.py +14 -14
- flask_appbuilder/api/__init__.py +741 -527
- flask_appbuilder/api/convert.py +104 -98
- flask_appbuilder/api/manager.py +14 -8
- flask_appbuilder/api/schemas.py +12 -1
- flask_appbuilder/babel/manager.py +12 -16
- flask_appbuilder/base.py +353 -280
- flask_appbuilder/basemanager.py +1 -1
- flask_appbuilder/baseviews.py +241 -164
- flask_appbuilder/charts/jsontools.py +10 -10
- flask_appbuilder/charts/views.py +56 -60
- flask_appbuilder/cli.py +115 -70
- flask_appbuilder/const.py +52 -52
- flask_appbuilder/exceptions.py +67 -5
- flask_appbuilder/fields.py +32 -23
- flask_appbuilder/fieldwidgets.py +34 -27
- flask_appbuilder/filemanager.py +33 -45
- flask_appbuilder/filters.py +11 -13
- flask_appbuilder/forms.py +31 -35
- flask_appbuilder/hooks.py +90 -0
- flask_appbuilder/menu.py +35 -10
- flask_appbuilder/models/base.py +47 -57
- flask_appbuilder/models/decorators.py +13 -13
- flask_appbuilder/models/filters.py +42 -38
- flask_appbuilder/models/generic/__init__.py +29 -29
- flask_appbuilder/models/generic/filters.py +11 -3
- flask_appbuilder/models/generic/interface.py +1 -3
- flask_appbuilder/models/group.py +37 -39
- flask_appbuilder/models/mixins.py +22 -18
- flask_appbuilder/models/sqla/__init__.py +19 -72
- flask_appbuilder/models/sqla/base.py +24 -0
- flask_appbuilder/models/sqla/base_legacy.py +132 -0
- flask_appbuilder/models/sqla/filters.py +132 -19
- flask_appbuilder/models/sqla/interface.py +390 -276
- flask_appbuilder/security/api.py +31 -35
- flask_appbuilder/security/decorators.py +181 -83
- flask_appbuilder/security/forms.py +20 -31
- flask_appbuilder/security/manager.py +715 -489
- flask_appbuilder/security/registerviews.py +29 -112
- flask_appbuilder/security/schemas.py +43 -0
- flask_appbuilder/security/sqla/apis/__init__.py +8 -0
- flask_appbuilder/security/sqla/apis/group/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/group/api.py +227 -0
- flask_appbuilder/security/sqla/apis/group/schema.py +73 -0
- flask_appbuilder/security/sqla/apis/permission/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/permission/api.py +19 -0
- flask_appbuilder/security/sqla/apis/permission_view_menu/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/permission_view_menu/api.py +16 -0
- flask_appbuilder/security/sqla/apis/role/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/role/api.py +306 -0
- flask_appbuilder/security/sqla/apis/role/schema.py +27 -0
- flask_appbuilder/security/sqla/apis/user/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/user/api.py +292 -0
- flask_appbuilder/security/sqla/apis/user/schema.py +97 -0
- flask_appbuilder/security/sqla/apis/user/validator.py +27 -0
- flask_appbuilder/security/sqla/apis/view_menu/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/view_menu/api.py +18 -0
- flask_appbuilder/security/sqla/manager.py +421 -203
- flask_appbuilder/security/sqla/models.py +192 -57
- flask_appbuilder/security/utils.py +9 -0
- flask_appbuilder/security/views.py +232 -229
- flask_appbuilder/static/.DS_Store +0 -0
- flask_appbuilder/static/appbuilder/css/ab.css +20 -12
- flask_appbuilder/static/appbuilder/css/bootstrap-datepicker/bootstrap-datepicker3.min.css +7 -0
- flask_appbuilder/static/appbuilder/css/bootstrap.min.css.map +1 -0
- flask_appbuilder/static/appbuilder/css/flags/flags16.css +249 -245
- flask_appbuilder/static/appbuilder/css/fontawesome/all.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/brands.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/fontawesome.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/regular.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/solid.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/svg-with-js.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/v4-font-face.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/v4-shims.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/v5-font-face.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/images/flags16.png +0 -0
- flask_appbuilder/static/appbuilder/css/select2/select2-bootstrap.min.css +7 -0
- flask_appbuilder/static/appbuilder/css/select2/select2.min.css +1 -0
- flask_appbuilder/static/appbuilder/css/swagger/swagger-ui.css +3 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.woff2 +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.woff2 +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.woff2 +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.woff2 +0 -0
- flask_appbuilder/static/appbuilder/js/ab.js +33 -23
- flask_appbuilder/static/appbuilder/js/ab_filters.js +91 -84
- flask_appbuilder/static/appbuilder/js/bootstrap-datepicker/bootstrap-datepicker.min.js +8 -0
- flask_appbuilder/static/appbuilder/js/jquery-latest.js +2 -2
- flask_appbuilder/static/appbuilder/js/select2/select2.min.js +2 -0
- flask_appbuilder/static/appbuilder/js/swagger-ui-bundle.js +3 -0
- flask_appbuilder/templates/appbuilder/baselib.html +9 -3
- flask_appbuilder/templates/appbuilder/general/lib.html +60 -34
- flask_appbuilder/templates/appbuilder/general/model/edit.html +1 -1
- flask_appbuilder/templates/appbuilder/general/model/edit_cascade.html +1 -1
- flask_appbuilder/templates/appbuilder/general/model/search.html +3 -2
- flask_appbuilder/templates/appbuilder/general/model/show.html +1 -1
- flask_appbuilder/templates/appbuilder/general/model/show_cascade.html +1 -1
- flask_appbuilder/templates/appbuilder/general/security/login_db.html +7 -7
- flask_appbuilder/templates/appbuilder/general/security/login_ldap.html +5 -5
- flask_appbuilder/templates/appbuilder/general/security/login_oauth.html +24 -49
- flask_appbuilder/templates/appbuilder/general/widgets/base_list.html +2 -1
- flask_appbuilder/templates/appbuilder/general/widgets/chart.html +4 -2
- flask_appbuilder/templates/appbuilder/general/widgets/direct_chart.html +4 -3
- flask_appbuilder/templates/appbuilder/general/widgets/multiple_chart.html +3 -2
- flask_appbuilder/templates/appbuilder/general/widgets/search.html +11 -10
- flask_appbuilder/templates/appbuilder/init.html +37 -43
- flask_appbuilder/templates/appbuilder/navbar_menu.html +1 -1
- flask_appbuilder/templates/appbuilder/navbar_right.html +2 -2
- flask_appbuilder/templates/appbuilder/swagger/swagger.html +22 -19
- flask_appbuilder/translations/de/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/de/LC_MESSAGES/messages.po +305 -161
- flask_appbuilder/translations/fa/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/fa/LC_MESSAGES/messages.po +802 -0
- flask_appbuilder/translations/fr/LC_MESSAGES/messages.po +461 -319
- flask_appbuilder/translations/pt_BR/LC_MESSAGES/messages.po +650 -650
- flask_appbuilder/translations/ru/LC_MESSAGES/messages.po +1 -1
- flask_appbuilder/translations/sl/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/sl/LC_MESSAGES/messages.po +690 -0
- flask_appbuilder/translations/tr/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/tr/LC_MESSAGES/messages.po +1015 -0
- flask_appbuilder/upload.py +20 -22
- flask_appbuilder/urltools.py +39 -19
- flask_appbuilder/utils/base.py +76 -0
- flask_appbuilder/utils/legacy.py +33 -0
- flask_appbuilder/utils/limit.py +20 -0
- flask_appbuilder/validators.py +73 -14
- flask_appbuilder/views.py +75 -424
- flask_appbuilder/widgets.py +50 -51
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/METADATA +36 -76
- flask_appbuilder-5.0.2.dist-info/RECORD +240 -0
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/WHEEL +1 -1
- flask_appbuilder-5.0.2.dist-info/entry_points.txt +2 -0
- Flask_AppBuilder-3.2.1rc1.dist-info/RECORD +0 -270
- Flask_AppBuilder-3.2.1rc1.dist-info/entry_points.txt +0 -6
- flask_appbuilder/console.py +0 -426
- flask_appbuilder/models/mongoengine/__init__.py +0 -0
- flask_appbuilder/models/mongoengine/fields.py +0 -65
- flask_appbuilder/models/mongoengine/filters.py +0 -145
- flask_appbuilder/models/mongoengine/interface.py +0 -328
- flask_appbuilder/security/mongoengine/__init__.py +0 -0
- flask_appbuilder/security/mongoengine/manager.py +0 -402
- flask_appbuilder/security/mongoengine/models.py +0 -120
- flask_appbuilder/static/appbuilder/css/font-awesome.min.css +0 -4
- flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.css +0 -9
- flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.js +0 -28
- flask_appbuilder/static/appbuilder/fonts/FontAwesome.otf +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.eot +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.svg +0 -2671
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.ttf +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff2 +0 -0
- flask_appbuilder/static/appbuilder/img/aol.png +0 -0
- flask_appbuilder/static/appbuilder/img/flags/flags16.png +0 -0
- flask_appbuilder/static/appbuilder/img/flickr.png +0 -0
- flask_appbuilder/static/appbuilder/img/google.png +0 -0
- flask_appbuilder/static/appbuilder/img/myopenid.png +0 -0
- flask_appbuilder/static/appbuilder/img/yahoo.png +0 -0
- flask_appbuilder/static/appbuilder/js/_google_charts.js +0 -39
- flask_appbuilder/static/appbuilder/js/html5shiv.js +0 -8
- flask_appbuilder/static/appbuilder/js/respond.min.js +0 -6
- flask_appbuilder/static/appbuilder/select2/select2-spinner.gif +0 -0
- flask_appbuilder/static/appbuilder/select2/select2.css +0 -1205
- flask_appbuilder/static/appbuilder/select2/select2.js +0 -23
- flask_appbuilder/static/appbuilder/select2/select2.png +0 -0
- flask_appbuilder/static/appbuilder/select2/select2x2.png +0 -0
- flask_appbuilder/templates/appbuilder/general/security/login_oid.html +0 -129
- flask_appbuilder/templates/appbuilder/general/security/resetpassword.html +0 -29
- flask_appbuilder/tests/__init__.py +0 -0
- flask_appbuilder/tests/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/__init__.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_auth_ldap.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_auth_oauth.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_ldapsearch.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_oauth_registration_role.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/base.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/base.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/config_api.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/config_api.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/const.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/const.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_api.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_api.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_menu.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_menu.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_mongoengine.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_mvc.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_mvc.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-37.pyc +0 -0
- flask_appbuilder/tests/_test_auth_ldap.py +0 -1045
- flask_appbuilder/tests/_test_auth_oauth.py +0 -419
- flask_appbuilder/tests/_test_ldapsearch.py +0 -135
- flask_appbuilder/tests/_test_oauth_registration_role.py +0 -59
- flask_appbuilder/tests/app.db +0 -0
- flask_appbuilder/tests/base.py +0 -90
- flask_appbuilder/tests/config_api.py +0 -21
- flask_appbuilder/tests/const.py +0 -9
- flask_appbuilder/tests/mongoengine/__init__.py +0 -0
- flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-37.pyc +0 -0
- flask_appbuilder/tests/mongoengine/__pycache__/models.cpython-36.pyc +0 -0
- flask_appbuilder/tests/mongoengine/models.py +0 -41
- flask_appbuilder/tests/sqla/__init__.py +0 -0
- flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-37.pyc +0 -0
- flask_appbuilder/tests/sqla/__pycache__/models.cpython-36.pyc +0 -0
- flask_appbuilder/tests/sqla/__pycache__/models.cpython-37.pyc +0 -0
- flask_appbuilder/tests/sqla/models.py +0 -340
- flask_appbuilder/tests/test_0_fixture.py +0 -39
- flask_appbuilder/tests/test_api.py +0 -2790
- flask_appbuilder/tests/test_fab_cli.py +0 -72
- flask_appbuilder/tests/test_menu.py +0 -122
- flask_appbuilder/tests/test_mongoengine.py +0 -572
- flask_appbuilder/tests/test_mvc.py +0 -1710
- flask_appbuilder/tests/test_sqlalchemy.py +0 -24
- flask_appbuilder/translations/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/translations/es/LC_MESSAGES/messages.po~ +0 -582
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/LICENSE +0 -0
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/top_level.txt +0 -0
|
@@ -2,9 +2,15 @@ import datetime
|
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
4
|
from dateutil import parser
|
|
5
|
+
from flask import current_app
|
|
6
|
+
from flask_appbuilder.exceptions import ApplyFilterException
|
|
7
|
+
from flask_appbuilder.models.filters import (
|
|
8
|
+
BaseFilter,
|
|
9
|
+
BaseFilterConverter,
|
|
10
|
+
FilterRelation,
|
|
11
|
+
)
|
|
5
12
|
from flask_babel import lazy_gettext
|
|
6
|
-
|
|
7
|
-
from ..filters import BaseFilter, BaseFilterConverter, FilterRelation
|
|
13
|
+
from sqlalchemy.exc import SQLAlchemyError
|
|
8
14
|
|
|
9
15
|
log = logging.getLogger(__name__)
|
|
10
16
|
|
|
@@ -15,11 +21,14 @@ __all__ = [
|
|
|
15
21
|
"FilterNotStartsWith",
|
|
16
22
|
"FilterStartsWith",
|
|
17
23
|
"FilterContains",
|
|
24
|
+
"FilterNotContains",
|
|
18
25
|
"FilterNotEqual",
|
|
19
26
|
"FilterEndsWith",
|
|
20
27
|
"FilterEqualFunction",
|
|
21
28
|
"FilterGreater",
|
|
22
29
|
"FilterNotEndsWith",
|
|
30
|
+
"FilterIn",
|
|
31
|
+
"FilterNotIn",
|
|
23
32
|
"FilterRelationManyToManyEqual",
|
|
24
33
|
"FilterRelationOneToManyEqual",
|
|
25
34
|
"FilterRelationOneToManyNotEqual",
|
|
@@ -29,13 +38,13 @@ __all__ = [
|
|
|
29
38
|
|
|
30
39
|
def get_field_setup_query(query, model, column_name):
|
|
31
40
|
"""
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
Help function for SQLA filters, checks for dot notation on column names.
|
|
42
|
+
If it exists, will join the query with the model
|
|
43
|
+
from the first part of the field name.
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
example:
|
|
46
|
+
Contact.created_by: if created_by is a User model,
|
|
47
|
+
it will be joined to the query.
|
|
39
48
|
"""
|
|
40
49
|
if not hasattr(model, column_name):
|
|
41
50
|
# it's an inner obj attr
|
|
@@ -72,6 +81,9 @@ def set_value_to_type(datamodel, column_name, value):
|
|
|
72
81
|
return parser.parse(value)
|
|
73
82
|
except Exception:
|
|
74
83
|
return None
|
|
84
|
+
elif datamodel.is_json(column_name):
|
|
85
|
+
# For JSON columns, treat as string for filtering
|
|
86
|
+
return str(value)
|
|
75
87
|
return value
|
|
76
88
|
|
|
77
89
|
|
|
@@ -178,13 +190,46 @@ class FilterSmaller(BaseFilter):
|
|
|
178
190
|
return query.filter(field < value)
|
|
179
191
|
|
|
180
192
|
|
|
193
|
+
class FilterIn(BaseFilter):
|
|
194
|
+
name = lazy_gettext("In")
|
|
195
|
+
arg_name = "in"
|
|
196
|
+
|
|
197
|
+
def apply(self, query, value):
|
|
198
|
+
query, field = get_field_setup_query(query, self.model, self.column_name)
|
|
199
|
+
typed_values = [
|
|
200
|
+
set_value_to_type(self.datamodel, self.column_name, v) for v in value
|
|
201
|
+
]
|
|
202
|
+
return query.filter(field.in_(typed_values))
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class FilterNotIn(BaseFilter):
|
|
206
|
+
name = lazy_gettext("Not In")
|
|
207
|
+
arg_name = "not_in"
|
|
208
|
+
|
|
209
|
+
def apply(self, query, value):
|
|
210
|
+
query, field = get_field_setup_query(query, self.model, self.column_name)
|
|
211
|
+
typed_values = [
|
|
212
|
+
set_value_to_type(self.datamodel, self.column_name, v) for v in value
|
|
213
|
+
]
|
|
214
|
+
return query.filter(~field.in_(typed_values))
|
|
215
|
+
|
|
216
|
+
|
|
181
217
|
class FilterRelationOneToManyEqual(FilterRelation):
|
|
182
218
|
name = lazy_gettext("Relation")
|
|
183
219
|
arg_name = "rel_o_m"
|
|
184
220
|
|
|
185
221
|
def apply(self, query, value):
|
|
186
222
|
query, field = get_field_setup_query(query, self.model, self.column_name)
|
|
187
|
-
|
|
223
|
+
try:
|
|
224
|
+
rel_obj = self.datamodel.get_related_obj(self.column_name, value)
|
|
225
|
+
except SQLAlchemyError as exc:
|
|
226
|
+
logging.warning("Filter exception for %s will not apply", field)
|
|
227
|
+
try:
|
|
228
|
+
current_app.appbuilder.session.rollback()
|
|
229
|
+
except SQLAlchemyError:
|
|
230
|
+
# on MSSQL a rollback would fail here
|
|
231
|
+
pass
|
|
232
|
+
raise ApplyFilterException(exception=exc)
|
|
188
233
|
return query.filter(field == rel_obj)
|
|
189
234
|
|
|
190
235
|
|
|
@@ -194,7 +239,16 @@ class FilterRelationOneToManyNotEqual(FilterRelation):
|
|
|
194
239
|
|
|
195
240
|
def apply(self, query, value):
|
|
196
241
|
query, field = get_field_setup_query(query, self.model, self.column_name)
|
|
197
|
-
|
|
242
|
+
try:
|
|
243
|
+
rel_obj = self.datamodel.get_related_obj(self.column_name, value)
|
|
244
|
+
except SQLAlchemyError as exc:
|
|
245
|
+
log.warning("Filter exception for %s will not apply", field)
|
|
246
|
+
try:
|
|
247
|
+
current_app.appbuilder.session.rollback()
|
|
248
|
+
except SQLAlchemyError:
|
|
249
|
+
# on MSSQL a rollback would fail here
|
|
250
|
+
pass
|
|
251
|
+
raise ApplyFilterException(exception=exc)
|
|
198
252
|
return query.filter(field != rel_obj)
|
|
199
253
|
|
|
200
254
|
|
|
@@ -207,15 +261,27 @@ class FilterRelationManyToManyEqual(FilterRelation):
|
|
|
207
261
|
Get object by column_name and value_item, then apply filter if object exists
|
|
208
262
|
Query with new filter applied
|
|
209
263
|
"""
|
|
210
|
-
|
|
264
|
+
try:
|
|
265
|
+
rel_obj = self.datamodel.get_related_obj(self.column_name, value_item)
|
|
266
|
+
except SQLAlchemyError as exc:
|
|
267
|
+
logging.warning(
|
|
268
|
+
"Filter exception for %s with value %s, will not apply",
|
|
269
|
+
field,
|
|
270
|
+
value_item,
|
|
271
|
+
)
|
|
272
|
+
try:
|
|
273
|
+
current_app.appbuilder.session.rollback()
|
|
274
|
+
except SQLAlchemyError:
|
|
275
|
+
# on MSSQL a rollback would fail here
|
|
276
|
+
pass
|
|
277
|
+
raise ApplyFilterException(exception=exc)
|
|
211
278
|
|
|
212
279
|
if rel_obj:
|
|
213
280
|
return query.filter(field.contains(rel_obj))
|
|
214
281
|
else:
|
|
215
|
-
log.
|
|
216
|
-
"Related object for column: %s
|
|
282
|
+
log.warning(
|
|
283
|
+
"Related object for column: %s returned Null",
|
|
217
284
|
self.column_name,
|
|
218
|
-
value_item,
|
|
219
285
|
)
|
|
220
286
|
|
|
221
287
|
return query
|
|
@@ -251,8 +317,8 @@ class FilterInFunction(BaseFilter):
|
|
|
251
317
|
|
|
252
318
|
class SQLAFilterConverter(BaseFilterConverter):
|
|
253
319
|
"""
|
|
254
|
-
|
|
255
|
-
|
|
320
|
+
Class for converting columns into a supported list of filters
|
|
321
|
+
specific for SQLAlchemy.
|
|
256
322
|
|
|
257
323
|
"""
|
|
258
324
|
|
|
@@ -279,6 +345,8 @@ class SQLAFilterConverter(BaseFilterConverter):
|
|
|
279
345
|
FilterNotEndsWith,
|
|
280
346
|
FilterNotContains,
|
|
281
347
|
FilterNotEqual,
|
|
348
|
+
FilterIn,
|
|
349
|
+
FilterNotIn,
|
|
282
350
|
],
|
|
283
351
|
),
|
|
284
352
|
(
|
|
@@ -305,12 +373,57 @@ class SQLAFilterConverter(BaseFilterConverter):
|
|
|
305
373
|
FilterNotEndsWith,
|
|
306
374
|
FilterNotContains,
|
|
307
375
|
FilterNotEqual,
|
|
376
|
+
FilterIn,
|
|
377
|
+
FilterNotIn,
|
|
378
|
+
],
|
|
379
|
+
),
|
|
380
|
+
(
|
|
381
|
+
"is_integer",
|
|
382
|
+
[
|
|
383
|
+
FilterEqual,
|
|
384
|
+
FilterGreater,
|
|
385
|
+
FilterSmaller,
|
|
386
|
+
FilterNotEqual,
|
|
387
|
+
FilterIn,
|
|
388
|
+
FilterNotIn,
|
|
389
|
+
],
|
|
390
|
+
),
|
|
391
|
+
(
|
|
392
|
+
"is_float",
|
|
393
|
+
[
|
|
394
|
+
FilterEqual,
|
|
395
|
+
FilterGreater,
|
|
396
|
+
FilterSmaller,
|
|
397
|
+
FilterNotEqual,
|
|
398
|
+
FilterIn,
|
|
399
|
+
FilterNotIn,
|
|
400
|
+
],
|
|
401
|
+
),
|
|
402
|
+
(
|
|
403
|
+
"is_numeric",
|
|
404
|
+
[
|
|
405
|
+
FilterEqual,
|
|
406
|
+
FilterGreater,
|
|
407
|
+
FilterSmaller,
|
|
408
|
+
FilterNotEqual,
|
|
409
|
+
FilterIn,
|
|
410
|
+
FilterNotIn,
|
|
308
411
|
],
|
|
309
412
|
),
|
|
310
|
-
("is_integer", [FilterEqual, FilterGreater, FilterSmaller, FilterNotEqual]),
|
|
311
|
-
("is_float", [FilterEqual, FilterGreater, FilterSmaller, FilterNotEqual]),
|
|
312
|
-
("is_numeric", [FilterEqual, FilterGreater, FilterSmaller, FilterNotEqual]),
|
|
313
413
|
("is_date", [FilterEqual, FilterGreater, FilterSmaller, FilterNotEqual]),
|
|
314
414
|
("is_boolean", [FilterEqual, FilterNotEqual]),
|
|
315
415
|
("is_datetime", [FilterEqual, FilterGreater, FilterSmaller, FilterNotEqual]),
|
|
416
|
+
(
|
|
417
|
+
"is_json",
|
|
418
|
+
[
|
|
419
|
+
FilterStartsWith,
|
|
420
|
+
FilterEndsWith,
|
|
421
|
+
FilterContains,
|
|
422
|
+
FilterEqual,
|
|
423
|
+
FilterNotStartsWith,
|
|
424
|
+
FilterNotEndsWith,
|
|
425
|
+
FilterNotContains,
|
|
426
|
+
FilterNotEqual,
|
|
427
|
+
],
|
|
428
|
+
),
|
|
316
429
|
)
|