flask-appbuilder 3.2.1__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.1.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.1.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.1.dist-info/RECORD +0 -270
- Flask_AppBuilder-3.2.1.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.1.dist-info → flask_appbuilder-5.0.2.dist-info}/LICENSE +0 -0
- {Flask_AppBuilder-3.2.1.dist-info → flask_appbuilder-5.0.2.dist-info}/top_level.txt +0 -0
flask_appbuilder/const.py
CHANGED
|
@@ -17,111 +17,105 @@ from flask_babel import lazy_gettext
|
|
|
17
17
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
LOGMSG_ERR_SEC_ACCESS_DENIED = "Access is Denied for:
|
|
20
|
+
LOGMSG_ERR_SEC_ACCESS_DENIED = "Access is Denied for: %s on: %s"
|
|
21
21
|
""" Access denied log message, format with user and view/resource """
|
|
22
|
-
LOGMSG_WAR_SEC_LOGIN_FAILED = "Login Failed for user:
|
|
23
|
-
LOGMSG_ERR_SEC_CREATE_DB = "DB Creation and initialization failed:
|
|
22
|
+
LOGMSG_WAR_SEC_LOGIN_FAILED = "Login Failed for user: %s"
|
|
23
|
+
LOGMSG_ERR_SEC_CREATE_DB = "DB Creation and initialization failed: %s"
|
|
24
24
|
""" security models creation fails, format with error message """
|
|
25
|
-
LOGMSG_ERR_SEC_ADD_ROLE = "Add Role:
|
|
25
|
+
LOGMSG_ERR_SEC_ADD_ROLE = "Add Role: %s"
|
|
26
26
|
""" Error adding role, format with err message """
|
|
27
|
-
|
|
27
|
+
LOGMSG_ERR_SEC_ADD_GROUP = "Add Group: %s"
|
|
28
|
+
""" Error adding group, format with err message """
|
|
29
|
+
LOGMSG_ERR_SEC_ADD_PERMISSION = "Add Permission: %s"
|
|
28
30
|
""" Error adding permission, format with err message """
|
|
29
|
-
LOGMSG_ERR_SEC_ADD_VIEWMENU = "Add View Menu Error:
|
|
31
|
+
LOGMSG_ERR_SEC_ADD_VIEWMENU = "Add View Menu Error: %s"
|
|
30
32
|
""" Error adding view menu, format with err message """
|
|
31
|
-
LOGMSG_ERR_SEC_DEL_PERMISSION = "Del Permission Error:
|
|
33
|
+
LOGMSG_ERR_SEC_DEL_PERMISSION = "Del Permission Error: %s"
|
|
32
34
|
""" Error deleting permission, format with err message """
|
|
33
|
-
LOGMSG_ERR_SEC_ADD_PERMVIEW = "Creation of Permission View Error:
|
|
35
|
+
LOGMSG_ERR_SEC_ADD_PERMVIEW = "Creation of Permission View Error: %s"
|
|
34
36
|
""" Error adding permission view, format with err message """
|
|
35
|
-
LOGMSG_ERR_SEC_DEL_PERMVIEW = "Remove Permission from View Error:
|
|
37
|
+
LOGMSG_ERR_SEC_DEL_PERMVIEW = "Remove Permission from View Error: %s"
|
|
36
38
|
""" Error deleting permission view, format with err message """
|
|
37
39
|
LOGMSG_WAR_SEC_DEL_PERMVIEW = (
|
|
38
|
-
"Refused to delete permission view, assoc with role exists
|
|
40
|
+
"Refused to delete permission view, assoc with role exists %s.%s %s"
|
|
39
41
|
)
|
|
40
|
-
LOGMSG_WAR_SEC_DEL_PERMISSION = "Refused to delete, permission
|
|
41
|
-
LOGMSG_WAR_SEC_DEL_VIEWMENU = "Refused to delete, view menu
|
|
42
|
-
LOGMSG_WAR_SEC_DEL_PERM_PVM = "Refused to delete permission
|
|
43
|
-
LOGMSG_WAR_SEC_DEL_VIEWMENU_PVM = "Refused to delete view menu
|
|
44
|
-
LOGMSG_ERR_SEC_ADD_PERMROLE = "Add Permission to Role Error:
|
|
42
|
+
LOGMSG_WAR_SEC_DEL_PERMISSION = "Refused to delete, permission %s does not exist"
|
|
43
|
+
LOGMSG_WAR_SEC_DEL_VIEWMENU = "Refused to delete, view menu %s does not exist"
|
|
44
|
+
LOGMSG_WAR_SEC_DEL_PERM_PVM = "Refused to delete permission %s, PVM exists %s"
|
|
45
|
+
LOGMSG_WAR_SEC_DEL_VIEWMENU_PVM = "Refused to delete view menu %s, PVM exists %s"
|
|
46
|
+
LOGMSG_ERR_SEC_ADD_PERMROLE = "Add Permission to Role Error: %s"
|
|
45
47
|
""" Error adding permission to role, format with err message """
|
|
46
|
-
LOGMSG_ERR_SEC_DEL_PERMROLE = "Remove Permission to Role Error:
|
|
48
|
+
LOGMSG_ERR_SEC_DEL_PERMROLE = "Remove Permission to Role Error: %s"
|
|
47
49
|
""" Error deleting permission to role, format with err message """
|
|
48
|
-
LOGMSG_ERR_SEC_ADD_REGISTER_USER = "Add Register User Error:
|
|
50
|
+
LOGMSG_ERR_SEC_ADD_REGISTER_USER = "Add Register User Error: %s"
|
|
49
51
|
""" Error adding registered user, format with err message """
|
|
50
|
-
LOGMSG_ERR_SEC_DEL_REGISTER_USER = "Remove Register User Error:
|
|
52
|
+
LOGMSG_ERR_SEC_DEL_REGISTER_USER = "Remove Register User Error: %s"
|
|
51
53
|
""" Error deleting registered user, format with err message """
|
|
52
|
-
LOGMSG_ERR_SEC_NO_REGISTER_HASH = "Attempt to activate user with false hash:
|
|
54
|
+
LOGMSG_ERR_SEC_NO_REGISTER_HASH = "Attempt to activate user with false hash: %s"
|
|
53
55
|
""" Attempt to activate user with not registered hash, format with hash """
|
|
54
|
-
LOGMSG_ERR_SEC_AUTH_LDAP = "LDAP Error
|
|
56
|
+
LOGMSG_ERR_SEC_AUTH_LDAP = "LDAP Error %s"
|
|
55
57
|
""" Generic LDAP error, format with err message """
|
|
56
58
|
LOGMSG_ERR_SEC_AUTH_LDAP_TLS = (
|
|
57
|
-
"LDAP Could not activate TLS on established connection with
|
|
59
|
+
"LDAP Could not activate TLS on established connection with %s"
|
|
58
60
|
)
|
|
59
61
|
""" LDAP Could not activate TLS on established connection with server """
|
|
60
|
-
LOGMSG_ERR_SEC_ADD_USER = "Error adding new user to database.
|
|
62
|
+
LOGMSG_ERR_SEC_ADD_USER = "Error adding new user to database. %s"
|
|
61
63
|
""" Error adding user, format with err message """
|
|
62
|
-
LOGMSG_ERR_SEC_UPD_USER = "Error updating user to database.
|
|
64
|
+
LOGMSG_ERR_SEC_UPD_USER = "Error updating user to database. %s "
|
|
63
65
|
""" Error updating user, format with err message """
|
|
64
66
|
LOGMSG_WAR_SEC_NO_USER = "No user yet created, use flask fab command to do it."
|
|
65
67
|
""" Warning when app starts if no user exists on db """
|
|
66
|
-
LOGMSG_WAR_SEC_NOLDAP_OBJ = "No LDAP object found for:
|
|
68
|
+
LOGMSG_WAR_SEC_NOLDAP_OBJ = "No LDAP object found for: %s"
|
|
67
69
|
|
|
68
|
-
LOGMSG_INF_SEC_ADD_PERMVIEW = "Created Permission View:
|
|
70
|
+
LOGMSG_INF_SEC_ADD_PERMVIEW = "Created Permission View: %s"
|
|
69
71
|
""" Info when adding permission view, format with permission view class string """
|
|
70
|
-
LOGMSG_INF_SEC_DEL_PERMVIEW = "Removed Permission View:
|
|
72
|
+
LOGMSG_INF_SEC_DEL_PERMVIEW = "Removed Permission View: %s on %s"
|
|
71
73
|
""" Info when deleting permission view, format with permission name and view name """
|
|
72
|
-
LOGMSG_INF_SEC_ADD_PERMROLE = "Added Permission
|
|
74
|
+
LOGMSG_INF_SEC_ADD_PERMROLE = "Added Permission %s to role %s"
|
|
73
75
|
""" Info when adding permission to role,
|
|
74
76
|
format with permission view class string and role name """
|
|
75
|
-
LOGMSG_INF_SEC_DEL_PERMROLE = "Removed Permission
|
|
77
|
+
LOGMSG_INF_SEC_DEL_PERMROLE = "Removed Permission %s to role %s"
|
|
76
78
|
""" Info when deleting permission to role,
|
|
77
79
|
format with permission view class string and role name """
|
|
78
|
-
LOGMSG_INF_SEC_ADD_ROLE = "Inserted Role:
|
|
80
|
+
LOGMSG_INF_SEC_ADD_ROLE = "Inserted Role: %s"
|
|
79
81
|
""" Info when added role, format with role name """
|
|
80
82
|
LOGMSG_INF_SEC_NO_DB = "Security DB not found Creating all Models from Base"
|
|
81
83
|
LOGMSG_INF_SEC_ADD_DB = "Security DB Created"
|
|
82
|
-
LOGMSG_INF_SEC_ADD_USER = "Added user
|
|
84
|
+
LOGMSG_INF_SEC_ADD_USER = "Added user %s"
|
|
83
85
|
""" User added, format with username """
|
|
84
|
-
LOGMSG_INF_SEC_UPD_USER = "Updated user
|
|
86
|
+
LOGMSG_INF_SEC_UPD_USER = "Updated user %s"
|
|
85
87
|
""" User updated, format with username """
|
|
86
|
-
LOGMSG_INF_SEC_UPD_ROLE = "Updated role
|
|
88
|
+
LOGMSG_INF_SEC_UPD_ROLE = "Updated role %s"
|
|
87
89
|
""" Role updated, format with role name """
|
|
88
|
-
LOGMSG_ERR_SEC_UPD_ROLE = "An error occurred updating role
|
|
90
|
+
LOGMSG_ERR_SEC_UPD_ROLE = "An error occurred updating role %s"
|
|
89
91
|
""" Role updated Error, format with role name """
|
|
90
92
|
|
|
91
|
-
LOGMSG_INF_FAB_ADDON_ADDED = "Registered AddOn:
|
|
93
|
+
LOGMSG_INF_FAB_ADDON_ADDED = "Registered AddOn: %s"
|
|
92
94
|
""" Addon imported and registered """
|
|
93
|
-
LOGMSG_ERR_FAB_ADDON_IMPORT = "An error occurred when importing declared addon
|
|
95
|
+
LOGMSG_ERR_FAB_ADDON_IMPORT = "An error occurred when importing declared addon %s: %s"
|
|
94
96
|
""" Error on addon import, format with addon class path and error message """
|
|
95
|
-
LOGMSG_ERR_FAB_ADDON_PROCESS =
|
|
96
|
-
"An error occurred when processing declared addon {0}: {1}"
|
|
97
|
-
)
|
|
97
|
+
LOGMSG_ERR_FAB_ADDON_PROCESS = "An error occurred when processing declared addon %s: %s"
|
|
98
98
|
""" Error on addon processing (pre, register, post),
|
|
99
99
|
format with addon class path and error message """
|
|
100
100
|
|
|
101
101
|
|
|
102
|
-
LOGMSG_ERR_FAB_ADD_PERMISSION_MENU = "Add Permission on Menu Error:
|
|
102
|
+
LOGMSG_ERR_FAB_ADD_PERMISSION_MENU = "Add Permission on Menu Error: %s"
|
|
103
103
|
""" Error when adding a permission to a menu, format with err """
|
|
104
|
-
LOGMSG_ERR_FAB_ADD_PERMISSION_VIEW = "Add Permission on View Error:
|
|
104
|
+
LOGMSG_ERR_FAB_ADD_PERMISSION_VIEW = "Add Permission on View Error: %s"
|
|
105
105
|
""" Error when adding a permission to a menu, format with err """
|
|
106
106
|
|
|
107
|
-
LOGMSG_ERR_DBI_ADD_GENERIC = "Add record error: {0}"
|
|
108
|
-
""" Database add generic error, format with err message """
|
|
109
|
-
LOGMSG_ERR_DBI_EDIT_GENERIC = "Edit record error: {0}"
|
|
110
|
-
""" Database edit generic error, format with err message """
|
|
111
|
-
LOGMSG_ERR_DBI_DEL_GENERIC = "Delete record error: {0}"
|
|
112
|
-
""" Database delete generic error, format with err message """
|
|
113
107
|
LOGMSG_WAR_DBI_AVG_ZERODIV = "Zero division on aggregate_avg"
|
|
114
108
|
|
|
115
|
-
LOGMSG_WAR_FAB_VIEW_EXISTS = "View already exists
|
|
109
|
+
LOGMSG_WAR_FAB_VIEW_EXISTS = "View already exists %s ignoring"
|
|
116
110
|
""" Attempt to add an already added view, format with view name """
|
|
117
|
-
LOGMSG_WAR_DBI_ADD_INTEGRITY = "Add record integrity error:
|
|
111
|
+
LOGMSG_WAR_DBI_ADD_INTEGRITY = "Add record integrity error: %s"
|
|
118
112
|
""" Dabase integrity error, format with err message """
|
|
119
|
-
LOGMSG_WAR_DBI_EDIT_INTEGRITY = "Edit record integrity error:
|
|
113
|
+
LOGMSG_WAR_DBI_EDIT_INTEGRITY = "Edit record integrity error: %s"
|
|
120
114
|
""" Dabase integrity error, format with err message """
|
|
121
|
-
LOGMSG_WAR_DBI_DEL_INTEGRITY = "Delete record integrity error:
|
|
115
|
+
LOGMSG_WAR_DBI_DEL_INTEGRITY = "Delete record integrity error: %s"
|
|
122
116
|
""" Dabase integrity error, format with err message """
|
|
123
117
|
|
|
124
|
-
LOGMSG_INF_FAB_ADD_VIEW = "Registering class
|
|
118
|
+
LOGMSG_INF_FAB_ADD_VIEW = "Registering class %s on menu %s"
|
|
125
119
|
""" Inform that view class was added, format with class name, name"""
|
|
126
120
|
|
|
127
121
|
|
|
@@ -132,7 +126,6 @@ FLAMSG_ERR_SEC_ACCESS_DENIED = lazy_gettext("Access is Denied")
|
|
|
132
126
|
PERMISSION_PREFIX = "can_"
|
|
133
127
|
""" Prefix to be concatenated to permission names, and inserted in the backend """
|
|
134
128
|
|
|
135
|
-
AUTH_OID = 0
|
|
136
129
|
AUTH_DB = 1
|
|
137
130
|
AUTH_LDAP = 2
|
|
138
131
|
AUTH_REMOTE_USER = 3
|
|
@@ -183,6 +176,7 @@ API_DESCRIPTION_COLUMNS_RIS_KEY = "description_columns"
|
|
|
183
176
|
API_FILTERS_RIS_KEY = "filters"
|
|
184
177
|
API_PERMISSIONS_RIS_KEY = "permissions"
|
|
185
178
|
API_SELECT_COLUMNS_RIS_KEY = "columns"
|
|
179
|
+
API_SELECT_SEL_COLUMNS_RIS_KEY = "select_columns"
|
|
186
180
|
API_SELECT_KEYS_RIS_KEY = "keys"
|
|
187
181
|
API_ORDER_COLUMN_RIS_KEY = "order_column"
|
|
188
182
|
API_ORDER_DIRECTION_RIS_KEY = "order_direction"
|
|
@@ -193,3 +187,9 @@ API_LIST_TITLE_RIS_KEY = "list_title"
|
|
|
193
187
|
API_ADD_TITLE_RIS_KEY = "add_title"
|
|
194
188
|
API_EDIT_TITLE_RIS_KEY = "edit_title"
|
|
195
189
|
API_SHOW_TITLE_RIS_KEY = "show_title"
|
|
190
|
+
|
|
191
|
+
# -----------------------------------
|
|
192
|
+
# OAuth Provider Constants
|
|
193
|
+
# -----------------------------------
|
|
194
|
+
|
|
195
|
+
MICROSOFT_KEY_SET_URL = "https://login.microsoftonline.com/common/discovery/keys"
|
flask_appbuilder/exceptions.py
CHANGED
|
@@ -1,28 +1,90 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
class FABException(Exception):
|
|
2
5
|
"""Base FAB Exception"""
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
def __init__(self, *args, exception: Optional[Exception] = None) -> None:
|
|
8
|
+
self.exception = exception
|
|
9
|
+
super().__init__(*args)
|
|
10
|
+
|
|
11
|
+
def __str__(self):
|
|
12
|
+
return (
|
|
13
|
+
f"{self.__class__.__name__}: {self.exception.__class__.__name__}"
|
|
14
|
+
if self.exception
|
|
15
|
+
else super().__str__()
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DatabaseException(FABException):
|
|
20
|
+
"""Database related exception"""
|
|
5
21
|
|
|
6
22
|
|
|
7
23
|
class InvalidColumnFilterFABException(FABException):
|
|
8
24
|
"""Invalid column for filter"""
|
|
9
25
|
|
|
10
|
-
|
|
26
|
+
...
|
|
11
27
|
|
|
12
28
|
|
|
13
29
|
class InvalidOperationFilterFABException(FABException):
|
|
14
30
|
"""Invalid operation for filter"""
|
|
15
31
|
|
|
16
|
-
|
|
32
|
+
...
|
|
17
33
|
|
|
18
34
|
|
|
19
35
|
class InvalidOrderByColumnFABException(FABException):
|
|
20
36
|
"""Invalid order by column"""
|
|
21
37
|
|
|
22
|
-
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class InvalidColumnArgsFABException(FABException):
|
|
42
|
+
"""Invalid combination of column arguments"""
|
|
43
|
+
|
|
44
|
+
...
|
|
23
45
|
|
|
24
46
|
|
|
25
47
|
class InterfaceQueryWithoutSession(FABException):
|
|
26
48
|
"""You need to setup a session on the interface to perform queries"""
|
|
27
49
|
|
|
28
|
-
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class PasswordComplexityValidationError(FABException):
|
|
54
|
+
"""Raise this when implementing your own password complexity function"""
|
|
55
|
+
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ApplyFilterException(FABException):
|
|
60
|
+
"""When executing an apply filter a SQLAlchemy exception happens"""
|
|
61
|
+
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class OAuthProviderUnknown(FABException):
|
|
66
|
+
"""
|
|
67
|
+
When an OAuth provider is not supported/unknown
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class InvalidLoginAttempt(FABException):
|
|
74
|
+
"""
|
|
75
|
+
When the credentials entered could not be verified
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class DeleteGroupWithUsersException(FABException):
|
|
82
|
+
"""
|
|
83
|
+
When trying to delete a group with users
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class DeleteRoleWithUsersException(FABException):
|
|
88
|
+
"""
|
|
89
|
+
When trying to delete a role with users
|
|
90
|
+
"""
|
flask_appbuilder/fields.py
CHANGED
|
@@ -2,25 +2,28 @@ from __future__ import unicode_literals
|
|
|
2
2
|
|
|
3
3
|
import operator
|
|
4
4
|
|
|
5
|
+
from packaging import version
|
|
6
|
+
import wtforms
|
|
5
7
|
from wtforms import widgets
|
|
6
|
-
from wtforms.compat import string_types, text_type
|
|
7
8
|
from wtforms.fields import Field, SelectField, SelectFieldBase
|
|
8
9
|
from wtforms.validators import ValidationError
|
|
9
10
|
|
|
11
|
+
IS_WTFORMS_LESS_THEN_3_1_0 = version.parse(wtforms.__version__) < version.parse("3.1.0")
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
class AJAXSelectField(Field):
|
|
12
15
|
"""
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
Simple class to convert primary key to ORM objects
|
|
17
|
+
for SQLAlchemy and fab normal processing on add and update
|
|
18
|
+
This WTF field class is prepared to be used in related views or directly on forms.
|
|
19
|
+
|
|
20
|
+
:param label: The label to render on form
|
|
21
|
+
:param validators: A list of form validators
|
|
22
|
+
:param: datamodel: An initialized SQLAInterface with a model
|
|
23
|
+
:param: col_name: The column that maps to the model
|
|
24
|
+
:param: is_related:
|
|
25
|
+
If the model column is a relationship or direct on
|
|
26
|
+
this case use col_name with the pk
|
|
24
27
|
"""
|
|
25
28
|
|
|
26
29
|
def __init__(
|
|
@@ -78,7 +81,7 @@ class AJAXSelectField(Field):
|
|
|
78
81
|
|
|
79
82
|
class QuerySelectField(SelectFieldBase):
|
|
80
83
|
"""
|
|
81
|
-
|
|
84
|
+
Based on WTForms QuerySelectField
|
|
82
85
|
"""
|
|
83
86
|
|
|
84
87
|
widget = widgets.Select()
|
|
@@ -100,7 +103,7 @@ class QuerySelectField(SelectFieldBase):
|
|
|
100
103
|
|
|
101
104
|
if get_label is None:
|
|
102
105
|
self.get_label = lambda x: x
|
|
103
|
-
elif isinstance(get_label,
|
|
106
|
+
elif isinstance(get_label, str):
|
|
104
107
|
self.get_label = operator.attrgetter(get_label)
|
|
105
108
|
else:
|
|
106
109
|
self.get_label = get_label
|
|
@@ -126,17 +129,21 @@ class QuerySelectField(SelectFieldBase):
|
|
|
126
129
|
def _get_object_list(self):
|
|
127
130
|
if self._object_list is None:
|
|
128
131
|
objs = self.query_func()
|
|
129
|
-
self._object_list = list(
|
|
130
|
-
(text_type(self.get_pk_func(obj)), obj) for obj in objs
|
|
131
|
-
)
|
|
132
|
+
self._object_list = list((str(self.get_pk_func(obj)), obj) for obj in objs)
|
|
132
133
|
return self._object_list
|
|
133
134
|
|
|
134
135
|
def iter_choices(self):
|
|
135
136
|
if self.allow_blank:
|
|
136
|
-
|
|
137
|
+
if IS_WTFORMS_LESS_THEN_3_1_0:
|
|
138
|
+
yield ("__None", self.blank_text, self.data is None)
|
|
139
|
+
else:
|
|
140
|
+
yield ("__None", self.blank_text, self.data is None, {})
|
|
137
141
|
|
|
138
142
|
for pk, obj in self._get_object_list():
|
|
139
|
-
|
|
143
|
+
if IS_WTFORMS_LESS_THEN_3_1_0:
|
|
144
|
+
yield (pk, self.get_label(obj), obj == self.data)
|
|
145
|
+
else:
|
|
146
|
+
yield (pk, self.get_label(obj), obj == self.data, {})
|
|
140
147
|
|
|
141
148
|
def process_formdata(self, valuelist):
|
|
142
149
|
if valuelist:
|
|
@@ -206,7 +213,10 @@ class QuerySelectMultipleField(QuerySelectField):
|
|
|
206
213
|
|
|
207
214
|
def iter_choices(self):
|
|
208
215
|
for pk, obj in self._get_object_list():
|
|
209
|
-
|
|
216
|
+
if IS_WTFORMS_LESS_THEN_3_1_0:
|
|
217
|
+
yield (pk, self.get_label(obj), obj in self.data)
|
|
218
|
+
else:
|
|
219
|
+
yield (pk, self.get_label(obj), obj in self.data, {})
|
|
210
220
|
|
|
211
221
|
def process_formdata(self, valuelist):
|
|
212
222
|
self._formdata = set(valuelist)
|
|
@@ -243,8 +253,7 @@ class EnumField(SelectField):
|
|
|
243
253
|
# Column(Enum(enum.Enum)) case
|
|
244
254
|
if enum_class is not None:
|
|
245
255
|
labels = [
|
|
246
|
-
|
|
247
|
-
for enum_member in enums
|
|
256
|
+
str(enum_class.__members__[enum_member].value) for enum_member in enums
|
|
248
257
|
]
|
|
249
258
|
|
|
250
259
|
def coerce(value):
|
|
@@ -262,7 +271,7 @@ class EnumField(SelectField):
|
|
|
262
271
|
def coerce(value):
|
|
263
272
|
if value is None:
|
|
264
273
|
return None
|
|
265
|
-
return
|
|
274
|
+
return str(value)
|
|
266
275
|
|
|
267
276
|
choices = list(zip(enums, labels))
|
|
268
277
|
|
flask_appbuilder/fieldwidgets.py
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
from flask_babel import lazy_gettext as _
|
|
2
|
+
from markupsafe import Markup
|
|
2
3
|
from wtforms import widgets
|
|
3
|
-
from wtforms.widgets import html_params
|
|
4
|
+
from wtforms.widgets import html_params
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
class DatePickerWidget
|
|
7
|
+
class DatePickerWidget:
|
|
7
8
|
"""
|
|
8
9
|
Date Time picker from Eonasdan GitHub
|
|
9
10
|
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
data_template = (
|
|
13
|
-
'<div class="input-group date appbuilder_date"
|
|
14
|
+
'<div class="input-group date appbuilder_date"'
|
|
15
|
+
' data-provide="datepicker" id="datepicker">'
|
|
14
16
|
'<span class="input-group-addon"><i class="fa fa-calendar cursor-hand"></i>'
|
|
15
17
|
"</span>"
|
|
16
18
|
'<input class="form-control" data-format="yyyy-MM-dd" %(text)s />'
|
|
@@ -24,19 +26,20 @@ class DatePickerWidget(object):
|
|
|
24
26
|
field.data = ""
|
|
25
27
|
template = self.data_template
|
|
26
28
|
|
|
27
|
-
return
|
|
29
|
+
return Markup(
|
|
28
30
|
template % {"text": html_params(type="text", value=field.data, **kwargs)}
|
|
29
31
|
)
|
|
30
32
|
|
|
31
33
|
|
|
32
|
-
class DateTimePickerWidget
|
|
34
|
+
class DateTimePickerWidget:
|
|
33
35
|
"""
|
|
34
36
|
Date Time picker from Eonasdan GitHub
|
|
35
37
|
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
40
|
data_template = (
|
|
39
|
-
'<div class="input-group date appbuilder_datetime"
|
|
41
|
+
'<div class="input-group date appbuilder_datetime" '
|
|
42
|
+
'data-provide="datepicker" id="datetimepicker">'
|
|
40
43
|
'<span class="input-group-addon"><i class="fa fa-calendar cursor-hand"></i>'
|
|
41
44
|
"</span>"
|
|
42
45
|
'<input class="form-control" data-format="yyyy-MM-dd hh:mm:ss" %(text)s />'
|
|
@@ -50,14 +53,14 @@ class DateTimePickerWidget(object):
|
|
|
50
53
|
field.data = ""
|
|
51
54
|
template = self.data_template
|
|
52
55
|
|
|
53
|
-
return
|
|
56
|
+
return Markup(
|
|
54
57
|
template % {"text": html_params(type="text", value=field.data, **kwargs)}
|
|
55
58
|
)
|
|
56
59
|
|
|
57
60
|
|
|
58
61
|
class BS3TextFieldWidget(widgets.TextInput):
|
|
59
62
|
def __call__(self, field, **kwargs):
|
|
60
|
-
kwargs["class"] =
|
|
63
|
+
kwargs["class"] = "form-control"
|
|
61
64
|
if field.label:
|
|
62
65
|
kwargs["placeholder"] = field.label.text
|
|
63
66
|
if "name_" in kwargs:
|
|
@@ -67,7 +70,7 @@ class BS3TextFieldWidget(widgets.TextInput):
|
|
|
67
70
|
|
|
68
71
|
class BS3TextAreaFieldWidget(widgets.TextArea):
|
|
69
72
|
def __call__(self, field, **kwargs):
|
|
70
|
-
kwargs["class"] =
|
|
73
|
+
kwargs["class"] = "form-control"
|
|
71
74
|
kwargs["rows"] = 3
|
|
72
75
|
if field.label:
|
|
73
76
|
kwargs["placeholder"] = field.label.text
|
|
@@ -76,25 +79,26 @@ class BS3TextAreaFieldWidget(widgets.TextArea):
|
|
|
76
79
|
|
|
77
80
|
class BS3PasswordFieldWidget(widgets.PasswordInput):
|
|
78
81
|
def __call__(self, field, **kwargs):
|
|
79
|
-
kwargs["class"] =
|
|
82
|
+
kwargs["class"] = "form-control"
|
|
80
83
|
if field.label:
|
|
81
84
|
kwargs["placeholder"] = field.label.text
|
|
82
85
|
return super(BS3PasswordFieldWidget, self).__call__(field, **kwargs)
|
|
83
86
|
|
|
84
87
|
|
|
85
|
-
class Select2AJAXWidget
|
|
88
|
+
class Select2AJAXWidget:
|
|
86
89
|
data_template = "<input %(text)s />"
|
|
87
90
|
|
|
88
91
|
def __init__(self, endpoint, extra_classes=None, style=None):
|
|
89
92
|
self.endpoint = endpoint
|
|
90
93
|
self.extra_classes = extra_classes
|
|
91
|
-
self.style = style or
|
|
94
|
+
self.style = style or ""
|
|
92
95
|
|
|
93
96
|
def __call__(self, field, **kwargs):
|
|
94
97
|
kwargs.setdefault("id", field.id)
|
|
95
98
|
kwargs.setdefault("name", field.name)
|
|
96
99
|
kwargs.setdefault("endpoint", self.endpoint)
|
|
97
|
-
|
|
100
|
+
if self.style:
|
|
101
|
+
kwargs.setdefault("style", self.style)
|
|
98
102
|
input_classes = "input-group my_select2_ajax"
|
|
99
103
|
if self.extra_classes:
|
|
100
104
|
input_classes = input_classes + " " + self.extra_classes
|
|
@@ -103,26 +107,27 @@ class Select2AJAXWidget(object):
|
|
|
103
107
|
field.data = ""
|
|
104
108
|
template = self.data_template
|
|
105
109
|
|
|
106
|
-
return
|
|
110
|
+
return Markup(
|
|
107
111
|
template % {"text": html_params(type="text", value=field.data, **kwargs)}
|
|
108
112
|
)
|
|
109
113
|
|
|
110
114
|
|
|
111
|
-
class Select2SlaveAJAXWidget
|
|
115
|
+
class Select2SlaveAJAXWidget:
|
|
112
116
|
data_template = '<input class="input-group my_select2_ajax_slave" %(text)s />'
|
|
113
117
|
|
|
114
118
|
def __init__(self, master_id, endpoint, extra_classes=None, style=None):
|
|
115
119
|
self.endpoint = endpoint
|
|
116
120
|
self.master_id = master_id
|
|
117
121
|
self.extra_classes = extra_classes
|
|
118
|
-
self.style = style or
|
|
122
|
+
self.style = style or ""
|
|
119
123
|
|
|
120
124
|
def __call__(self, field, **kwargs):
|
|
121
125
|
kwargs.setdefault("id", field.id)
|
|
122
126
|
kwargs.setdefault("name", field.name)
|
|
123
127
|
kwargs.setdefault("endpoint", self.endpoint)
|
|
124
128
|
kwargs.setdefault("master_id", self.master_id)
|
|
125
|
-
|
|
129
|
+
if self.style:
|
|
130
|
+
kwargs.setdefault("style", self.style)
|
|
126
131
|
input_classes = "input-group my_select2_ajax"
|
|
127
132
|
if self.extra_classes:
|
|
128
133
|
input_classes = input_classes + " " + self.extra_classes
|
|
@@ -132,7 +137,7 @@ class Select2SlaveAJAXWidget(object):
|
|
|
132
137
|
field.data = ""
|
|
133
138
|
template = self.data_template
|
|
134
139
|
|
|
135
|
-
return
|
|
140
|
+
return Markup(
|
|
136
141
|
template % {"text": html_params(type="text", value=field.data, **kwargs)}
|
|
137
142
|
)
|
|
138
143
|
|
|
@@ -142,14 +147,15 @@ class Select2Widget(widgets.Select):
|
|
|
142
147
|
|
|
143
148
|
def __init__(self, extra_classes=None, style=None):
|
|
144
149
|
self.extra_classes = extra_classes
|
|
145
|
-
self.style = style
|
|
146
|
-
|
|
150
|
+
self.style = style
|
|
151
|
+
super(Select2Widget, self).__init__()
|
|
147
152
|
|
|
148
153
|
def __call__(self, field, **kwargs):
|
|
149
|
-
kwargs["class"] =
|
|
154
|
+
kwargs["class"] = "my_select2 form-control"
|
|
150
155
|
if self.extra_classes:
|
|
151
156
|
kwargs["class"] = kwargs["class"] + " " + self.extra_classes
|
|
152
|
-
|
|
157
|
+
if self.style:
|
|
158
|
+
kwargs["style"] = self.style
|
|
153
159
|
kwargs["data-placeholder"] = _("Select Value")
|
|
154
160
|
if "name_" in kwargs:
|
|
155
161
|
field.name = kwargs["name_"]
|
|
@@ -161,16 +167,17 @@ class Select2ManyWidget(widgets.Select):
|
|
|
161
167
|
|
|
162
168
|
def __init__(self, extra_classes=None, style=None):
|
|
163
169
|
self.extra_classes = extra_classes
|
|
164
|
-
self.style = style
|
|
165
|
-
|
|
170
|
+
self.style = style
|
|
171
|
+
super(Select2ManyWidget, self).__init__()
|
|
166
172
|
|
|
167
173
|
def __call__(self, field, **kwargs):
|
|
168
|
-
kwargs["class"] =
|
|
174
|
+
kwargs["class"] = "my_select2 form-control"
|
|
169
175
|
if self.extra_classes:
|
|
170
176
|
kwargs["class"] = kwargs["class"] + " " + self.extra_classes
|
|
171
|
-
|
|
177
|
+
if self.style:
|
|
178
|
+
kwargs["style"] = self.style
|
|
172
179
|
kwargs["data-placeholder"] = _("Select Value")
|
|
173
|
-
kwargs["multiple"] =
|
|
180
|
+
kwargs["multiple"] = "true"
|
|
174
181
|
if "name_" in kwargs:
|
|
175
182
|
field.name = kwargs["name_"]
|
|
176
183
|
return super(Select2ManyWidget, self).__call__(field, **kwargs)
|