Flask-Exts 0.2.2__tar.gz → 0.2.4__tar.gz
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_exts-0.2.2 → flask_exts-0.2.4}/.gitignore +3 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/CHANGES.rst +20 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/PKG-INFO +4 -1
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/configure.rst +3 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/index.rst +1 -0
- flask_exts-0.2.4/docs/user.rst +11 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/app.py +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/app.py +7 -5
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/pagination.html +1 -1
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/admin_views.py +6 -1
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/build_sample.py +16 -4
- flask_exts-0.2.4/examples/demo/file_op.py +13 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/make_app.py +18 -9
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/models/model.py → flask_exts-0.2.4/examples/demo/models/location_image.py +21 -5
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/tree.py +3 -2
- flask_exts-0.2.4/examples/demo/templates/my/index.html +7 -0
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/views/image_view.py → flask_exts-0.2.4/examples/demo/views/location_image_view.py +5 -4
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/fileadmin/make_app.py +2 -8
- flask_exts-0.2.4/examples/instance/config.py +3 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/rediscli.py +1 -1
- flask_exts-0.2.4/examples/simple.py +27 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/pyproject.toml +4 -1
- flask_exts-0.2.4/src/flask_exts/__about__.py +1 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/__init__.py +0 -1
- flask_exts-0.2.4/src/flask_exts/admin/admin.py +15 -0
- flask_exts-0.2.4/src/flask_exts/admin/base_admin.py +134 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/model/form.py +3 -3
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/model/view.py +8 -10
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/sqla/form.py +18 -18
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/sqla/view.py +4 -4
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/view.py +19 -28
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/commands.py +6 -6
- flask_exts-0.2.4/src/flask_exts/constants.py +6 -0
- flask_exts-0.2.4/src/flask_exts/datastore/sqla/__init__.py +9 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/datastore/sqla/models/role.py +0 -1
- flask_exts-0.2.4/src/flask_exts/datastore/sqla/models/user.py +75 -0
- flask_exts-0.2.4/src/flask_exts/datastore/sqla/models/user_profile.py +27 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/datastore/sqla/models/webauthn.py +9 -5
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/datastore/sqla/orm.py +2 -5
- flask_exts-0.2.4/src/flask_exts/email/base.py +66 -0
- flask_exts-0.2.4/src/flask_exts/email/reset_password_sender.py +12 -0
- flask_exts-0.2.4/src/flask_exts/email/sender.py +6 -0
- flask_exts-0.2.4/src/flask_exts/email/smtp.py +41 -0
- flask_exts-0.2.4/src/flask_exts/email/verify_email_sender.py +12 -0
- flask_exts-0.2.4/src/flask_exts/manager.py +68 -0
- flask_exts-0.2.4/src/flask_exts/proxies.py +22 -0
- {flask_exts-0.2.2/src/flask_exts/security/authorize → flask_exts-0.2.4/src/flask_exts/security/authorizer}/base.py +1 -1
- {flask_exts-0.2.2/src/flask_exts/security/authorize → flask_exts-0.2.4/src/flask_exts/security/authorizer}/casbin_authorizer.py +10 -17
- flask_exts-0.2.2/src/flask_exts/security/authorize/casbin_sqlalchemy_adapter/adapter.py → flask_exts-0.2.4/src/flask_exts/security/authorizer/sqlalchemy_adapter.py +2 -2
- flask_exts-0.2.4/src/flask_exts/security/core.py +35 -0
- flask_exts-0.2.4/src/flask_exts/security/email_verification.py +84 -0
- flask_exts-0.2.4/src/flask_exts/security/hasher.py +22 -0
- flask_exts-0.2.4/src/flask_exts/security/reset_password.py +78 -0
- flask_exts-0.2.4/src/flask_exts/security/serializer.py +50 -0
- flask_exts-0.2.4/src/flask_exts/security/two_factor_authentication.py +38 -0
- flask_exts-0.2.4/src/flask_exts/signals.py +7 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/modal.js +1 -1
- flask_exts-0.2.4/src/flask_exts/static/js/qrcode.js +1945 -0
- flask_exts-0.2.4/src/flask_exts/template/base.py +37 -0
- flask_exts-0.2.4/src/flask_exts/template/dataset.py +9 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/sqla.py +2 -2
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/form/base_form.py +1 -1
- flask_exts-0.2.4/src/flask_exts/template/form/csrf.py +65 -0
- flask_exts-0.2.4/src/flask_exts/template/form/form_opts.py +6 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/form/meta.py +2 -25
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template/form}/utils.py +0 -9
- flask_exts-0.2.4/src/flask_exts/template/forms/change_password.py +28 -0
- flask_exts-0.2.4/src/flask_exts/template/forms/forgot_password.py +19 -0
- flask_exts-0.2.4/src/flask_exts/template/forms/login.py +13 -0
- {flask_exts-0.2.2/src/flask_exts/security → flask_exts-0.2.4/src/flask_exts/template}/forms/profile.py +1 -1
- flask_exts-0.2.4/src/flask_exts/template/forms/recovery.py +10 -0
- flask_exts-0.2.2/src/flask_exts/security/forms/mixins.py → flask_exts-0.2.4/src/flask_exts/template/forms/register.py +2 -9
- flask_exts-0.2.4/src/flask_exts/template/forms/reset_password.py +16 -0
- flask_exts-0.2.4/src/flask_exts/template/forms/two_factor.py +10 -0
- flask_exts-0.2.4/src/flask_exts/template/funcs.py +39 -0
- flask_exts-0.2.4/src/flask_exts/template/plugin.py +18 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/template/theme.py +5 -12
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/base.html +5 -3
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/index.html +1 -1
- flask_exts-0.2.4/src/flask_exts/templates/admin/master.html +1 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/list.html +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/base.html +4 -6
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/bootstrap4/form.html +4 -4
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/bootstrap5/form.html +6 -6
- flask_exts-0.2.4/src/flask_exts/templates/layout.html +12 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/actions.html +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/form.html +1 -1
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/icon.html +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/menu.html +1 -1
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/row_actions.html +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/table.html +8 -7
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/vendor.html +0 -3
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/rediscli/response.html +1 -1
- flask_exts-0.2.4/src/flask_exts/templates/views/user/change_password.html +11 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/forgot_password.html +11 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/index.html +21 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/user/login.html +4 -3
- flask_exts-0.2.4/src/flask_exts/templates/views/user/recovery.html +10 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/recovery_codes.html +32 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/user/register.html +1 -1
- flask_exts-0.2.4/src/flask_exts/templates/views/user/reset_password.html +11 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/setup_tfa.html +44 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/show_tfa.html +38 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/verify_email.html +9 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/verify_tfa.html +11 -0
- flask_exts-0.2.4/src/flask_exts/templates/views/user/verify_tfa_modal.html +17 -0
- flask_exts-0.2.4/src/flask_exts/usercenter/base_user.py +14 -0
- flask_exts-0.2.4/src/flask_exts/usercenter/base_user_store.py +29 -0
- flask_exts-0.2.4/src/flask_exts/usercenter/core.py +43 -0
- flask_exts-0.2.2/src/flask_exts/security/usercenter/sqla_usercenter.py → flask_exts-0.2.4/src/flask_exts/usercenter/sqla_user_store.py +58 -40
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/utils/__init__.py +1 -1
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/utils/authorize.py +4 -4
- flask_exts-0.2.2/src/flask_exts/decorators/auth_required_decorator.py → flask_exts-0.2.4/src/flask_exts/utils/decorators.py +2 -2
- flask_exts-0.2.4/src/flask_exts/utils/flask.py +16 -0
- flask_exts-0.2.4/src/flask_exts/utils/image.py +12 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/utils/request_user.py +6 -6
- flask_exts-0.2.2/src/flask_exts/utils/flask.py → flask_exts-0.2.4/src/flask_exts/utils/url.py +0 -14
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/views/file_view/base_file_view.py +4 -3
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/views/index_view.py +3 -2
- flask_exts-0.2.4/src/flask_exts/views/user_view.py +300 -0
- {flask_exts-0.2.2/tests → flask_exts-0.2.4/tests/admin/customer}/conftest.py +10 -6
- flask_exts-0.2.4/tests/admin/customer/test_admin.py +97 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/test_basic.py +324 -413
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/test_form_rules.py +12 -19
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/test_inlineform.py +4 -4
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/test_multi_pk.py +13 -16
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/test_translation.py +1 -1
- flask_exts-0.2.4/tests/admin/test_base.py +153 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/test_model.py +79 -77
- flask_exts-0.2.4/tests/conftest.py +46 -0
- flask_exts-0.2.4/tests/email/test_base.py +18 -0
- flask_exts-0.2.4/tests/email/test_smtp.py +24 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/casbin_adapter/test_sqlalchemy_adapter.py +5 -5
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/test_casbin_auth.py +21 -19
- flask_exts-0.2.4/tests/security/test_core.py +49 -0
- flask_exts-0.2.4/tests/security/test_tfa.py +18 -0
- flask_exts-0.2.4/tests/template/bootstrap4/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_field.py +17 -21
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_form.py +40 -48
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_form_row.py +10 -14
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_hidden_errors.py +3 -4
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_icon_sprite.py +25 -30
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_messages.py +15 -19
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_pager.py +10 -12
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_pagination.py +9 -11
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap4/test_render_table.py +48 -55
- flask_exts-0.2.4/tests/template/bootstrap5/__init__.py +0 -0
- flask_exts-0.2.4/tests/template/bootstrap5/conftest.py +21 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap5/test_base.py +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap5/test_render_form.py +31 -37
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap5/test_render_form_row.py +4 -5
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap5/test_render_messages.py +2 -3
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/bootstrap5/test_render_pagination.py +5 -6
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/conftest.py +1 -1
- flask_exts-0.2.2/tests/forms/test_form.py → flask_exts-0.2.4/tests/template/forms/test_csrf.py +4 -3
- {flask_exts-0.2.2/tests → flask_exts-0.2.4/tests/template}/forms/test_fields.py +2 -2
- {flask_exts-0.2.2/tests → flask_exts-0.2.4/tests/template}/forms/test_filefield.py +1 -1
- {flask_exts-0.2.2/tests → flask_exts-0.2.4/tests/template}/forms/test_uploadfile.py +3 -3
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/macros/test_render_breadcrumb_item.py +4 -6
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/macros/test_render_nav_item.py +4 -6
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/template/test_base.py +2 -2
- flask_exts-0.2.4/tests/templates/mock.html +1 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/test_babel.py +7 -6
- flask_exts-0.2.4/tests/test_base.py +27 -0
- flask_exts-0.2.4/tests/test_flask.py +34 -0
- flask_exts-0.2.4/tests/usercenter/test_sqla_usercenter.py +34 -0
- flask_exts-0.2.4/tests/utils/test_image.py +7 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/utils/test_request_user.py +2 -2
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/utils/test_url.py +1 -1
- flask_exts-0.2.4/tests/views/files/dummy.txt +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/views/test_file_view.py +26 -28
- flask_exts-0.2.4/tests/views/test_user_view.py +483 -0
- flask_exts-0.2.2/examples/demo/templates/my/index.html +0 -7
- flask_exts-0.2.2/examples/simple.py +0 -13
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/__init__.py +0 -1
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/data.py +0 -23
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/make_app.py +0 -88
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/models/__init__.py +0 -1
- flask_exts-0.2.2/examples/sqla-custom-inline-forms/templates/admin/admin.html +0 -5
- flask_exts-0.2.2/src/flask_exts/__about__.py +0 -1
- flask_exts-0.2.2/src/flask_exts/admin/admin.py +0 -117
- flask_exts-0.2.2/src/flask_exts/datastore/sqla/__init__.py +0 -9
- flask_exts-0.2.2/src/flask_exts/datastore/sqla/models/user.py +0 -38
- flask_exts-0.2.2/src/flask_exts/datastore/sqla/models/user_role.py +0 -11
- flask_exts-0.2.2/src/flask_exts/decorators/__init__.py +0 -2
- flask_exts-0.2.2/src/flask_exts/forms/__init__.py +0 -3
- flask_exts-0.2.2/src/flask_exts/forms/form/__init__.py +0 -2
- flask_exts-0.2.2/src/flask_exts/forms/form/csrf.py +0 -57
- flask_exts-0.2.2/src/flask_exts/manager.py +0 -74
- flask_exts-0.2.2/src/flask_exts/proxies.py +0 -17
- flask_exts-0.2.2/src/flask_exts/security/authorize/__init__.py +0 -1
- flask_exts-0.2.2/src/flask_exts/security/authorize/casbin_sqlalchemy_adapter/__init__.py +0 -1
- flask_exts-0.2.2/src/flask_exts/security/core.py +0 -43
- flask_exts-0.2.2/src/flask_exts/security/forms/__init__.py +0 -2
- flask_exts-0.2.2/src/flask_exts/security/forms/login.py +0 -6
- flask_exts-0.2.2/src/flask_exts/security/forms/register.py +0 -6
- flask_exts-0.2.2/src/flask_exts/security/mixins/webauthn_mixin.py +0 -9
- flask_exts-0.2.2/src/flask_exts/security/usercenter/base.py +0 -21
- flask_exts-0.2.2/src/flask_exts/security/usercenter/memory_usercenter.py +0 -59
- flask_exts-0.2.2/src/flask_exts/template/__init__.py +0 -37
- flask_exts-0.2.2/src/flask_exts/template/utils.py +0 -51
- flask_exts-0.2.2/src/flask_exts/templates/admin/master.html +0 -1
- flask_exts-0.2.2/src/flask_exts/templates/layout.html +0 -21
- flask_exts-0.2.2/src/flask_exts/templates/views/user/index.html +0 -7
- flask_exts-0.2.2/src/flask_exts/views/user_view.py +0 -118
- flask_exts-0.2.2/tests/admin/test_base.py +0 -315
- flask_exts-0.2.2/tests/template/bootstrap5/conftest.py +0 -14
- flask_exts-0.2.2/tests/test_base.py +0 -19
- flask_exts-0.2.2/tests/views/test_user_view.py +0 -60
- {flask_exts-0.2.2 → flask_exts-0.2.4}/.github/workflows/release.yml +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/.readthedocs.yaml +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/LICENSE.rst +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/README.rst +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/babel/babel.cfg +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/babel/babel.sh +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/babel/messages.pot +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/Makefile +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/_static/logo.png +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/changes.rst +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/conf.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/develop.rst +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/examples.rst +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/make.bat +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/docs/requirements.txt +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/README.rst +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/static/favicon.ico +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/bootswatch.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/flash.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/form.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/icon.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/icons.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/index.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/mybase.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/nav.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/pagination.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap4/templates/table.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/static/favicon.ico +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/bootswatch.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/flash.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/form.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/icon.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/icons.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/index.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/mybase.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/nav.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/bootstrap5/templates/table.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/author.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/keyword.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/post.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/post_tag.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/tag.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/user.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/models/user_keyword.py +0 -0
- {flask_exts-0.2.2/examples/sqla-custom-inline-forms → flask_exts-0.2.4/examples/demo}/templates/field_list.html +0 -0
- {flask_exts-0.2.2/examples/sqla-custom-inline-forms → flask_exts-0.2.4/examples/demo}/templates/locations.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/templates/tree_list.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/author_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/keyword_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/my_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/post_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/tag_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/tree_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/demo/views/user_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/fileadmin/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/fileadmin/file_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/examples/fileadmin/tmp/bbb/a.txt +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/requirements/build.in +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/requirements/test.in +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/actions.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/menu.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/model/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/model/ajax.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/model/filters.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/model/typefmt.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/row_action.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/sqla/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/sqla/ajax.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/sqla/filters.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/admin/sqla/typefmt.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/babel/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/babel/selector.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/datastore/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/datastore/sqla/models/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/security/usercenter → flask_exts-0.2.4/src/flask_exts/email}/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/security/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/translations → flask_exts-0.2.4/src/flask_exts/security/authorizer}/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/security/principal/identity.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/security/principal/identity_context.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/security/principal/permission.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/security/principal/principal.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/css/admin.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/css/rediscli.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/actions.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/details_filter.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/filters.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/form.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/helper.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/rediscli.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/security/base64.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/js/security/webauthn.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/logo.png +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/bootstrap-icons.svg +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/font/bootstrap-icons.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/font/bootstrap-icons.json +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/font/bootstrap-icons.min.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/font/bootstrap-icons.scss +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/font/fonts/bootstrap-icons.woff +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap-icons/font/fonts/bootstrap-icons.woff2 +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap4/bootstrap.bundle.min.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap4/bootstrap.min.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap5/bootstrap.bundle.min.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/bootstrap5/bootstrap.min.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/daterangepicker/daterangepicker.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/daterangepicker/daterangepicker.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/jquery/jquery.min.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/moment.min.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/select2/select2.min.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/select2/select2.min.js +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/vanilla-editor/css/bootstrap-editable.css +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/vanilla-editor/img/clear.png +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/vanilla-editor/img/loading.gif +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/static/vendor/vanilla-editor/js/bootstrap-editable.min.js +0 -0
- {flask_exts-0.2.2/src/flask_exts/security/utils → flask_exts-0.2.4/src/flask_exts/template}/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/ajax_select.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/datetime.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/file.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/inline.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/json.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/recaptcha.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/select.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/switch.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/fields/taglist.py +0 -0
- {flask_exts-0.2.2/tests/admin → flask_exts-0.2.4/src/flask_exts/template/form}/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/form/flask_form.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/form/session_csrf.py +0 -0
- {flask_exts-0.2.2/tests/admin/sqla → flask_exts-0.2.4/src/flask_exts/template/forms}/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/rules.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/validators/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/validators/field_list.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/validators/file.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/validators/recaptcha.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/validators/sqla.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/__init__.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/checkbox.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/datetime.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/file.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/inline.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/recaptcha.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/render_template.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/select.py +0 -0
- {flask_exts-0.2.2/src/flask_exts/forms → flask_exts-0.2.4/src/flask_exts/template}/widgets/xeditable.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/create.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/details.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/edit.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/modals/create.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/modals/details.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/admin/model/modals/edit.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/bootstrap4/message.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/bootstrap4/pagination.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/bootstrap5/message.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/index.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/inline.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/layout.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/message.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/nav.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/macro/pagination.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/file/form.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/file/list.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/file/modals/form.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/rediscli/console.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/views/user/list.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/widgets/inline_field_list.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/templates/widgets/inline_form.html +0 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/src/flask_exts/translations}/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/translations/en/LC_MESSAGES/messages.mo +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/translations/en/LC_MESSAGES/messages.po +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/translations/zh_CN/LC_MESSAGES/messages.mo +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/translations/zh_CN/LC_MESSAGES/messages.po +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/types.py +0 -0
- {flask_exts-0.2.2/tests/template → flask_exts-0.2.4/src/flask_exts/usercenter}/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/utils/jwt.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/utils/sqla.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/utils/tools.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/views/file_view/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/views/file_view/local_file_storage.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/views/file_view/local_file_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/src/flask_exts/views/rediscli_view.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/__init__.py +0 -0
- {flask_exts-0.2.2/tests/template/bootstrap4 → flask_exts-0.2.4/tests/admin}/__init__.py +0 -0
- {flask_exts-0.2.2/tests → flask_exts-0.2.4/tests/admin/customer}/templates/mock.html +0 -0
- {flask_exts-0.2.2/tests/template/bootstrap5 → flask_exts-0.2.4/tests/admin/sqla}/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/templates/another_macro.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/admin/sqla/templates/macro.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/data/copyleft.gif +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/data/copyleft.jpeg +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/data/copyleft.jpg +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/data/copyleft.png +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/data/copyleft.tiff +0 -0
- /flask_exts-0.2.2/tests/funcs.py → /flask_exts-0.2.4/tests/helper.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/message.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/model1.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/multpk.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/polymorphic.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/tree.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/models/user.py +0 -0
- /flask_exts-0.2.2/src/flask_exts/utils/url.py → /flask_exts-0.2.4/tests/security/authorizer/__init__.py +0 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/casbin_adapter/rbac_model.conf +0 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/casbin_adapter/rbac_policy.csv +0 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/casbin_files/authz_policy.csv +0 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/casbin_files/rbac_model.conf +0 -0
- {flask_exts-0.2.2/tests/security/authorize → flask_exts-0.2.4/tests/security/authorizer}/casbin_files/rbac_policy.csv +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/security/test_principal.py +0 -0
- /flask_exts-0.2.2/tests/views/files/dummy.txt → /flask_exts-0.2.4/tests/template/__init__.py +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/templates/method.html +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/translations/en/LC_MESSAGES/messages.mo +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/translations/en/LC_MESSAGES/messages.po +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/translations/zh_CN/LC_MESSAGES/messages.po +0 -0
- {flask_exts-0.2.2 → flask_exts-0.2.4}/tests/views/test_rediscli_view.py +0 -0
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
v0.2.4
|
|
2
|
+
------
|
|
3
|
+
|
|
4
|
+
Unreleased
|
|
5
|
+
|
|
6
|
+
- user change password
|
|
7
|
+
- user forgot password
|
|
8
|
+
- user 2FA with TOTP
|
|
9
|
+
- user recovery codes
|
|
10
|
+
- user recovery
|
|
11
|
+
|
|
12
|
+
v0.2.3
|
|
13
|
+
------
|
|
14
|
+
|
|
15
|
+
Released 2025-08-28
|
|
16
|
+
|
|
17
|
+
- move form into template
|
|
18
|
+
- add folder email
|
|
19
|
+
- add security.email_verification
|
|
20
|
+
|
|
1
21
|
v0.2.2
|
|
2
22
|
------
|
|
3
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Flask-Exts
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Flask extensions with admin, SQLAlchemy, babel, forms, fields, widgets, and so on.
|
|
5
5
|
Project-URL: Documentation, https://flask-exts.readthedocs.io
|
|
6
6
|
Project-URL: Source, https://github.com/ojso/flask-exts
|
|
@@ -46,7 +46,10 @@ Requires-Dist: flask-babel>=4.0
|
|
|
46
46
|
Requires-Dist: flask-login>=0.6
|
|
47
47
|
Requires-Dist: flask-sqlalchemy>=3.0
|
|
48
48
|
Requires-Dist: flask>=3.0
|
|
49
|
+
Requires-Dist: pillow>=11.0
|
|
49
50
|
Requires-Dist: pyjwt>=2.0
|
|
51
|
+
Requires-Dist: pyotp>=2.0
|
|
52
|
+
Requires-Dist: qrcode>=8.0
|
|
50
53
|
Requires-Dist: tablib>=3.0
|
|
51
54
|
Requires-Dist: webauthn>=2.0
|
|
52
55
|
Requires-Dist: wtforms>=3.0
|
|
@@ -18,7 +18,8 @@ Configuration
|
|
|
18
18
|
Default is ``csrf_token``.
|
|
19
19
|
``CSRF_TIME_LIMIT`` Max age in seconds for CSRF tokens.
|
|
20
20
|
Default is ``1800``.
|
|
21
|
-
``
|
|
22
|
-
|
|
21
|
+
``NOREPLY_EMAIL_SENDER`` Email address used to send emails.
|
|
22
|
+
It is a dict for smtp with keys: host,port,user,password.
|
|
23
|
+
Default is None.
|
|
23
24
|
========================== =====================================================================
|
|
24
25
|
|
|
@@ -3,8 +3,8 @@ from flask import Flask, render_template, request, flash, redirect, url_for
|
|
|
3
3
|
from markupsafe import Markup
|
|
4
4
|
from wtforms.validators import DataRequired, Length, Regexp
|
|
5
5
|
from wtforms.fields import *
|
|
6
|
-
from flask_exts.
|
|
7
|
-
from flask_exts.
|
|
6
|
+
from flask_exts.template.form.flask_form import FlaskForm
|
|
7
|
+
from flask_exts.template.fields import SwitchField
|
|
8
8
|
from flask_exts import Manager
|
|
9
9
|
from flask_exts.datastore.sqla import db
|
|
10
10
|
|
|
@@ -4,13 +4,12 @@ from markupsafe import Markup
|
|
|
4
4
|
from wtforms.validators import DataRequired, Length, Regexp
|
|
5
5
|
from wtforms.fields import *
|
|
6
6
|
|
|
7
|
-
from flask_exts.
|
|
8
|
-
from flask_exts.
|
|
7
|
+
from flask_exts.template.form.flask_form import FlaskForm
|
|
8
|
+
from flask_exts.template.fields import SwitchField
|
|
9
9
|
from flask_exts import Manager
|
|
10
10
|
from flask_exts.template.theme import BootstrapTheme
|
|
11
11
|
from flask_exts.datastore.sqla import db
|
|
12
12
|
|
|
13
|
-
theme = BootstrapTheme(version=5)
|
|
14
13
|
|
|
15
14
|
app = Flask(__name__)
|
|
16
15
|
app.secret_key = "dev"
|
|
@@ -18,10 +17,13 @@ app.secret_key = "dev"
|
|
|
18
17
|
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
|
19
18
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
|
|
20
19
|
# set bootstrap5
|
|
21
|
-
app.config["TEMPLATE_THEME"] = theme
|
|
22
20
|
app.config['ADMIN_ENABLED'] = False
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
class MyManager(Manager):
|
|
23
|
+
def get_theme(self):
|
|
24
|
+
return BootstrapTheme(5)
|
|
25
|
+
|
|
26
|
+
manager = MyManager()
|
|
25
27
|
manager.init_app(app)
|
|
26
28
|
|
|
27
29
|
|
|
@@ -5,11 +5,12 @@ from .views.tree_view import treeview
|
|
|
5
5
|
from .views.tag_view import tagview
|
|
6
6
|
from .views.author_view import authorview
|
|
7
7
|
from .views.post_view import postview
|
|
8
|
+
from .views.location_image_view import locationview
|
|
8
9
|
from flask_exts.admin.menu import MenuLink
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def add_views(app):
|
|
12
|
-
admin = app.extensions["manager"].
|
|
13
|
+
admin = app.extensions["manager"].admin
|
|
13
14
|
|
|
14
15
|
admin.add_view(myview)
|
|
15
16
|
admin.add_view(userview)
|
|
@@ -18,6 +19,10 @@ def add_views(app):
|
|
|
18
19
|
admin.add_view(tagview)
|
|
19
20
|
admin.add_view(postview)
|
|
20
21
|
admin.add_view(treeview)
|
|
22
|
+
admin.add_view(locationview)
|
|
23
|
+
admin.menu.add_link(
|
|
24
|
+
MenuLink(name="locationlist", url="/locationlist", category="List")
|
|
25
|
+
)
|
|
21
26
|
admin.menu.add_category(name="Links")
|
|
22
27
|
admin.menu.add_link(MenuLink(name="Back Home", url="/", category="Links"))
|
|
23
28
|
admin.menu.add_sub_category(name='External',parent_name='Links')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import random
|
|
2
2
|
import datetime
|
|
3
|
-
from flask_exts.proxies import
|
|
3
|
+
from flask_exts.proxies import _userstore
|
|
4
4
|
from .models import db
|
|
5
5
|
from .models.author import Author
|
|
6
6
|
from .models.author import AVAILABLE_USER_TYPES
|
|
@@ -9,14 +9,25 @@ from .models.post import Post
|
|
|
9
9
|
from .models.tree import Tree
|
|
10
10
|
from .models.keyword import Keyword
|
|
11
11
|
from .models.user import MyUser
|
|
12
|
+
from .models.location_image import ImageType
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
def build_user_admin():
|
|
15
|
-
u, _ =
|
|
16
|
+
u, _ = _userstore.create_user(
|
|
16
17
|
username="admin", password="admin", email="admin@example.com"
|
|
17
18
|
)
|
|
18
|
-
r, _ =
|
|
19
|
-
|
|
19
|
+
r, _ = _userstore.create_role(name="admin")
|
|
20
|
+
_userstore.user_add_role(u, r)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def build_sample_image_type():
|
|
24
|
+
|
|
25
|
+
# Add some image types for the form_ajax_refs inside the inline_model
|
|
26
|
+
image_types = ("JPEG", "PNG", "GIF")
|
|
27
|
+
for image_type in image_types:
|
|
28
|
+
itype = ImageType(name=image_type)
|
|
29
|
+
db.session.add(itype)
|
|
30
|
+
db.session.commit()
|
|
20
31
|
|
|
21
32
|
|
|
22
33
|
def build_sample_userkeyword():
|
|
@@ -225,5 +236,6 @@ def build_sample_db():
|
|
|
225
236
|
build_sample_tree()
|
|
226
237
|
build_sample_post()
|
|
227
238
|
build_user_admin()
|
|
239
|
+
build_sample_image_type()
|
|
228
240
|
|
|
229
241
|
return
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import os.path as op
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
# Figure out base upload path
|
|
5
|
+
static_path = op.join(op.dirname(__file__), "static")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def remove_image(image_path):
|
|
9
|
+
os.remove(op.join(static_path, image_path))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def save_image(file_data, image_path):
|
|
13
|
+
file_data.save(op.join(static_path, image_path))
|
|
@@ -2,6 +2,11 @@ import os.path as op
|
|
|
2
2
|
from flask import Flask
|
|
3
3
|
from flask_exts import Manager
|
|
4
4
|
|
|
5
|
+
class MyManager(Manager):
|
|
6
|
+
def get_admin_class(self):
|
|
7
|
+
from flask_exts.admin.admin import Admin
|
|
8
|
+
return Admin
|
|
9
|
+
|
|
5
10
|
|
|
6
11
|
def get_sqlite_path():
|
|
7
12
|
app_dir = op.realpath(op.dirname(__file__))
|
|
@@ -10,26 +15,21 @@ def get_sqlite_path():
|
|
|
10
15
|
|
|
11
16
|
|
|
12
17
|
def create_app():
|
|
13
|
-
app = Flask(__name__)
|
|
18
|
+
app = Flask(__name__, instance_relative_config=True)
|
|
14
19
|
app.config["SECRET_KEY"] = "dev"
|
|
15
|
-
|
|
20
|
+
app.config.from_pyfile('config.py',silent=True)
|
|
21
|
+
app.config.from_pyfile('config_prod.py',silent=True)
|
|
16
22
|
# app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
|
|
17
23
|
# app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
|
|
18
24
|
# app.config["SQLALCHEMY_ECHO"] = True
|
|
19
25
|
app.config["DATABASE_FILE"] = get_sqlite_path()
|
|
20
26
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + app.config["DATABASE_FILE"]
|
|
21
|
-
# JWT
|
|
22
|
-
app.config["JWT_SECRET_KEY"] = "SECRET_KEY"
|
|
23
|
-
app.config["JWT_HASH"] = "HS256"
|
|
24
|
-
# app.config["ADMIN_ACCESS_ENABLED"] = False
|
|
25
27
|
init_app(app)
|
|
26
|
-
|
|
27
28
|
return app
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def init_app(app: Flask):
|
|
31
|
-
|
|
32
|
-
manager = Manager()
|
|
32
|
+
manager = MyManager()
|
|
33
33
|
manager.init_app(app)
|
|
34
34
|
|
|
35
35
|
from .models import init_models
|
|
@@ -40,6 +40,15 @@ def init_app(app: Flask):
|
|
|
40
40
|
|
|
41
41
|
add_views(app)
|
|
42
42
|
|
|
43
|
+
@app.route("/locationlist")
|
|
44
|
+
def location_list():
|
|
45
|
+
from .models.location_image import Location
|
|
46
|
+
from flask import render_template
|
|
47
|
+
from .models import db
|
|
48
|
+
|
|
49
|
+
locations = db.session.query(Location).all()
|
|
50
|
+
return render_template("locations.html", locations=locations)
|
|
51
|
+
|
|
43
52
|
if not op.exists(app.config["DATABASE_FILE"]):
|
|
44
53
|
with app.app_context():
|
|
45
54
|
from .build_sample import build_sample_db
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
from . import db
|
|
2
2
|
from typing import Optional
|
|
3
|
+
from typing import List
|
|
3
4
|
from sqlalchemy import ForeignKey
|
|
4
5
|
from sqlalchemy.orm import relationship
|
|
5
6
|
from sqlalchemy.orm import Mapped
|
|
6
7
|
from sqlalchemy.orm import mapped_column
|
|
7
|
-
|
|
8
|
+
from sqlalchemy import event
|
|
9
|
+
from ..file_op import remove_image
|
|
8
10
|
|
|
9
11
|
class Location(db.Model):
|
|
10
12
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
11
13
|
name: Mapped[str]
|
|
14
|
+
images: Mapped[List["LocationImage"]] = relationship(
|
|
15
|
+
"LocationImage", back_populates="location", cascade="all, delete-orphan"
|
|
16
|
+
)
|
|
12
17
|
|
|
13
18
|
|
|
14
19
|
class ImageType(db.Model):
|
|
@@ -33,10 +38,21 @@ class LocationImage(db.Model):
|
|
|
33
38
|
alt: Mapped[str]
|
|
34
39
|
path: Mapped[str]
|
|
35
40
|
|
|
36
|
-
location_id
|
|
37
|
-
location: Mapped["Location"] = relationship(
|
|
41
|
+
location_id = mapped_column(ForeignKey("location.id"))
|
|
42
|
+
location: Mapped["Location"] = relationship(back_populates="images")
|
|
43
|
+
|
|
44
|
+
image_type_id = mapped_column(ForeignKey("image_type.id"))
|
|
45
|
+
image_type: Mapped["ImageType"] = relationship()
|
|
46
|
+
|
|
38
47
|
|
|
39
|
-
image_type_id: Mapped[int] = mapped_column(ForeignKey("image_type.id"))
|
|
40
|
-
image_type: Mapped["ImageType"] = relationship(backref='images')
|
|
41
48
|
|
|
42
49
|
|
|
50
|
+
# Register after_delete handler which will delete image file after model gets deleted
|
|
51
|
+
@event.listens_for(Location, "after_delete")
|
|
52
|
+
def _handle_image_delete(mapper, conn, target):
|
|
53
|
+
for location_image in target.images:
|
|
54
|
+
try:
|
|
55
|
+
if location_image.path:
|
|
56
|
+
remove_image(location_image.path)
|
|
57
|
+
except:
|
|
58
|
+
pass
|
|
@@ -5,6 +5,7 @@ from sqlalchemy.orm import relationship
|
|
|
5
5
|
from sqlalchemy.orm import Mapped
|
|
6
6
|
from sqlalchemy.orm import mapped_column
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
class Tree(db.Model):
|
|
9
10
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
10
11
|
name: Mapped[str]
|
|
@@ -12,7 +13,7 @@ class Tree(db.Model):
|
|
|
12
13
|
# recursive relationship
|
|
13
14
|
parent_id: Mapped[Optional[int]] = mapped_column(ForeignKey("tree.id"))
|
|
14
15
|
parent = relationship("Tree", back_populates="children", remote_side=id)
|
|
15
|
-
children = relationship("Tree",back_populates="parent")
|
|
16
|
+
children = relationship("Tree", back_populates="parent")
|
|
16
17
|
|
|
17
18
|
def __str__(self):
|
|
18
|
-
return "{}".format(self.name)
|
|
19
|
+
return "{}".format(self.name)
|
|
@@ -3,12 +3,13 @@ from flask import request
|
|
|
3
3
|
from flask import current_app
|
|
4
4
|
from wtforms.fields import FileField
|
|
5
5
|
from flask_exts.admin.sqla.ajax import QueryAjaxModelLoader
|
|
6
|
-
from flask_exts.
|
|
6
|
+
from flask_exts.template.widgets.render_template import RenderTemplateWidget
|
|
7
7
|
from flask_exts.admin.model.form import InlineFormAdmin
|
|
8
8
|
from flask_exts.admin.sqla import ModelView
|
|
9
9
|
from flask_exts.admin.sqla.form import InlineModelConverter
|
|
10
|
-
from flask_exts.
|
|
11
|
-
from ..models.
|
|
10
|
+
from flask_exts.template.fields.sqla import InlineModelFormList
|
|
11
|
+
from ..models.location_image import ImageType, Location, LocationImage
|
|
12
|
+
from ..file_op import save_image
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
# This widget uses custom template for inline field list
|
|
@@ -60,7 +61,7 @@ class LocationImageInlineModelForm(InlineFormAdmin):
|
|
|
60
61
|
|
|
61
62
|
if file_data:
|
|
62
63
|
model.path = secure_filename(file_data.filename)
|
|
63
|
-
|
|
64
|
+
save_image(file_data, model.path)
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
# Administrative class
|
|
@@ -9,7 +9,7 @@ def create_app():
|
|
|
9
9
|
app = Flask(__name__)
|
|
10
10
|
app.config["SECRET_KEY"] = "dev"
|
|
11
11
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
init_app(app)
|
|
14
14
|
return app
|
|
15
15
|
|
|
@@ -22,11 +22,5 @@ def init_app(app: Flask):
|
|
|
22
22
|
# db.drop_all()
|
|
23
23
|
db.create_all()
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
@app.route("/")
|
|
27
|
-
def index():
|
|
28
|
-
|
|
29
|
-
return '<a href="/admin/">Click me to get to Admin!</a>'
|
|
30
|
-
|
|
31
|
-
admin = app.extensions["manager"].admins[0]
|
|
25
|
+
admin = manager.admins[0]
|
|
32
26
|
admin.add_view(file_view)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# simple.py
|
|
2
|
+
|
|
3
|
+
from flask import Flask
|
|
4
|
+
from flask_exts import Manager
|
|
5
|
+
from flask_exts.admin import expose
|
|
6
|
+
from flask_exts.admin import BaseView
|
|
7
|
+
from flask_exts.views.index_view import IndexView
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MockView(BaseView):
|
|
11
|
+
@expose("/")
|
|
12
|
+
def index(self):
|
|
13
|
+
return "Success!"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
app = Flask(__name__)
|
|
17
|
+
app.config["SECRET_KEY"] = "dev"
|
|
18
|
+
manager = Manager()
|
|
19
|
+
manager.init_app(app)
|
|
20
|
+
# Register the index view
|
|
21
|
+
manager.admin.add_view(IndexView(), is_menu=False)
|
|
22
|
+
# Register a mock view
|
|
23
|
+
manager.admin.add_view(MockView())
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if __name__ == "__main__":
|
|
27
|
+
app.run(debug=True)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.4"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .base_admin import BaseAdmin
|
|
2
|
+
from ..utils.authorize import authorize_allow
|
|
3
|
+
class Admin(BaseAdmin):
|
|
4
|
+
|
|
5
|
+
def allow(self, *args, **kwargs):
|
|
6
|
+
return authorize_allow(*args, **kwargs)
|
|
7
|
+
|
|
8
|
+
def init_views(self):
|
|
9
|
+
from ..views.index_view import IndexView
|
|
10
|
+
from ..views.user_view import UserView
|
|
11
|
+
index_view = IndexView()
|
|
12
|
+
self.add_view(index_view, is_menu=False)
|
|
13
|
+
|
|
14
|
+
user_view = UserView()
|
|
15
|
+
self.add_view(user_view, is_menu=False)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
from flask import render_template
|
|
2
|
+
from flask import url_for
|
|
3
|
+
from flask import make_response
|
|
4
|
+
from .menu import Menu
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseAdmin:
|
|
8
|
+
"""
|
|
9
|
+
Collection of the admin views. Also manages menu structure.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, app=None):
|
|
13
|
+
self.app = app
|
|
14
|
+
self.name = self.get_admin_name()
|
|
15
|
+
self.url = self.get_admin_url()
|
|
16
|
+
self.endpoint = self.get_admin_endpoint()
|
|
17
|
+
self.template_folder = self.get_admin_template_folder()
|
|
18
|
+
self.static_folder = self.get_admin_static_folder()
|
|
19
|
+
self._views = {}
|
|
20
|
+
self.menu = Menu(self)
|
|
21
|
+
self.init_views()
|
|
22
|
+
if app is not None:
|
|
23
|
+
self.init_app(app)
|
|
24
|
+
|
|
25
|
+
def init_app(self, app):
|
|
26
|
+
"""
|
|
27
|
+
Constructor.
|
|
28
|
+
|
|
29
|
+
:param app:
|
|
30
|
+
Flask application object
|
|
31
|
+
:param name:
|
|
32
|
+
Application name. Will be displayed in the main menu and as a page title. Defaults to "Admin"
|
|
33
|
+
:param url:
|
|
34
|
+
Base URL
|
|
35
|
+
:param endpoint:
|
|
36
|
+
Base endpoint name for index view. If you use multiple instances of the `Admin` class with
|
|
37
|
+
a single Flask application, you have to set a unique endpoint name for each instance.
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
self.app = app
|
|
41
|
+
|
|
42
|
+
# Register views
|
|
43
|
+
for v in self._views.values():
|
|
44
|
+
app.register_blueprint(v.create_blueprint())
|
|
45
|
+
|
|
46
|
+
def get_admin_name(self):
|
|
47
|
+
name = "Admin"
|
|
48
|
+
return name
|
|
49
|
+
|
|
50
|
+
def get_admin_url(self):
|
|
51
|
+
url = "/admin"
|
|
52
|
+
if not url.startswith("/"):
|
|
53
|
+
raise ValueError("admin.url must startswith /")
|
|
54
|
+
return url
|
|
55
|
+
|
|
56
|
+
def get_admin_endpoint(self):
|
|
57
|
+
return "admin"
|
|
58
|
+
|
|
59
|
+
def get_admin_template_folder(self):
|
|
60
|
+
template_folder = "../templates"
|
|
61
|
+
return template_folder
|
|
62
|
+
|
|
63
|
+
def get_admin_static_folder(self):
|
|
64
|
+
static_folder = "../static"
|
|
65
|
+
return static_folder
|
|
66
|
+
|
|
67
|
+
def add_view(self, view, is_menu=True, category=None):
|
|
68
|
+
"""
|
|
69
|
+
Add a view to the collection.
|
|
70
|
+
|
|
71
|
+
:param view:
|
|
72
|
+
View to add.
|
|
73
|
+
"""
|
|
74
|
+
# attach self(admin) to view
|
|
75
|
+
view.admin = self
|
|
76
|
+
|
|
77
|
+
# Add to _views
|
|
78
|
+
view_name = view.name.lower().replace(" ", "_")
|
|
79
|
+
|
|
80
|
+
if view_name in self._views:
|
|
81
|
+
raise ValueError(f"View with name {view.name} already exists")
|
|
82
|
+
|
|
83
|
+
self._views[view_name] = view
|
|
84
|
+
|
|
85
|
+
# If app was provided in constructor, register view with Flask app
|
|
86
|
+
if self.app is not None:
|
|
87
|
+
self.app.register_blueprint(view.create_blueprint())
|
|
88
|
+
|
|
89
|
+
if is_menu:
|
|
90
|
+
self.menu.add_view(view, category)
|
|
91
|
+
|
|
92
|
+
def get_url(self, endpoint, **kwargs):
|
|
93
|
+
"""
|
|
94
|
+
Generate URL for the endpoint.
|
|
95
|
+
|
|
96
|
+
:param endpoint:
|
|
97
|
+
Flask endpoint name
|
|
98
|
+
:param kwargs:
|
|
99
|
+
Arguments for `url_for`
|
|
100
|
+
"""
|
|
101
|
+
return url_for(endpoint, **kwargs)
|
|
102
|
+
|
|
103
|
+
def allow(self, *args, **kwargs):
|
|
104
|
+
return True
|
|
105
|
+
|
|
106
|
+
def init_views(self):
|
|
107
|
+
"""
|
|
108
|
+
Initialize views. This method can be overridden in subclasses to add custom views.
|
|
109
|
+
"""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
def render(self, template, **kwargs):
|
|
113
|
+
"""
|
|
114
|
+
Render template
|
|
115
|
+
|
|
116
|
+
:param template:
|
|
117
|
+
Template path to render
|
|
118
|
+
:param kwargs:
|
|
119
|
+
Template arguments
|
|
120
|
+
"""
|
|
121
|
+
# Add admin instance to kwargs
|
|
122
|
+
kwargs["admin"] = self
|
|
123
|
+
# Add URL generation method to kwargs
|
|
124
|
+
kwargs["get_url"] = self.get_url
|
|
125
|
+
|
|
126
|
+
# If _headers is provided in kwargs, use make_response to set headers
|
|
127
|
+
if "_headers" in kwargs:
|
|
128
|
+
headers = kwargs.pop("_headers")
|
|
129
|
+
response = make_response(render_template(template, **kwargs))
|
|
130
|
+
for key, value in headers.items():
|
|
131
|
+
response.headers[key] = value
|
|
132
|
+
return response
|
|
133
|
+
else:
|
|
134
|
+
return render_template(template, **kwargs)
|
|
@@ -3,9 +3,9 @@ import warnings
|
|
|
3
3
|
from wtforms.fields import HiddenField
|
|
4
4
|
from wtforms.fields.core import UnboundField
|
|
5
5
|
from wtforms.validators import InputRequired
|
|
6
|
-
from ...
|
|
7
|
-
from ...
|
|
8
|
-
from ...
|
|
6
|
+
from ...template.widgets import XEditableWidget
|
|
7
|
+
from ...template.form.base_form import BaseForm
|
|
8
|
+
from ...template.rules import RuleSet
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def converts(*args):
|