Flask-Exts 0.1.7__tar.gz → 0.2.0__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.
Files changed (263) hide show
  1. {flask_exts-0.1.7 → flask_exts-0.2.0}/CHANGES.rst +22 -2
  2. {flask_exts-0.1.7 → flask_exts-0.2.0}/PKG-INFO +3 -2
  3. flask_exts-0.2.0/docs/conf.py +62 -0
  4. flask_exts-0.1.7/docs/usage.rst → flask_exts-0.2.0/docs/configure.rst +14 -40
  5. flask_exts-0.1.7/docs/translation.rst → flask_exts-0.2.0/docs/develop.rst +53 -12
  6. {flask_exts-0.1.7 → flask_exts-0.2.0}/docs/index.rst +22 -5
  7. flask_exts-0.2.0/docs/requirements.txt +2 -0
  8. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/README.rst +24 -24
  9. flask_exts-0.2.0/examples/admin/fileadmin/admin_app.py +17 -0
  10. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/app.py +2 -2
  11. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/mybase.html +1 -0
  12. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/app.py +4 -4
  13. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/mybase.html +1 -0
  14. flask_exts-0.2.0/examples/demo/__init__.py +1 -0
  15. flask_exts-0.2.0/examples/demo/make_app.py +52 -0
  16. flask_exts-0.2.0/examples/demo/models/__init__.py +16 -0
  17. flask_exts-0.2.0/examples/demo/models/user.py +16 -0
  18. flask_exts-0.2.0/examples/demo/sample.sqlite +0 -0
  19. flask_exts-0.2.0/examples/demo/templates/my/index.html +6 -0
  20. flask_exts-0.2.0/examples/demo/user_center.py +54 -0
  21. flask_exts-0.2.0/examples/demo/views/my_view.py +10 -0
  22. flask_exts-0.2.0/examples/simple.py +17 -0
  23. {flask_exts-0.1.7 → flask_exts-0.2.0}/pyproject.toml +1 -0
  24. flask_exts-0.2.0/src/flask_exts/__about__.py +1 -0
  25. flask_exts-0.2.0/src/flask_exts/admin/actions.py +121 -0
  26. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/admin/admin.py +59 -40
  27. flask_exts-0.2.0/src/flask_exts/admin/file_admin/__init__.py +1 -0
  28. flask_exts-0.2.0/src/flask_exts/admin/file_admin/base_file_admin.py +1162 -0
  29. flask_exts-0.2.0/src/flask_exts/admin/file_admin/local_file_admin.py +15 -0
  30. flask_exts-0.2.0/src/flask_exts/admin/file_admin/local_file_storage.py +122 -0
  31. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/admin/menu.py +3 -4
  32. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/admin/view.py +24 -48
  33. flask_exts-0.1.7/src/flask_exts/admin/admin_index_view.py → flask_exts-0.2.0/src/flask_exts/admin/views/index_view.py +15 -10
  34. flask_exts-0.2.0/src/flask_exts/admin/views/user_view.py +129 -0
  35. flask_exts-0.2.0/src/flask_exts/forms/__init__.py +1 -0
  36. flask_exts-0.2.0/src/flask_exts/forms/fields/__init__.py +4 -0
  37. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/datetime.py +4 -4
  38. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/select.py +3 -3
  39. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/taglist.py +2 -3
  40. flask_exts-0.2.0/src/flask_exts/forms/form/__init__.py +2 -0
  41. flask_exts-0.2.0/src/flask_exts/forms/form/base_form.py +16 -0
  42. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/form/csrf.py +5 -7
  43. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/form/flask_form.py +1 -11
  44. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/form/meta.py +9 -5
  45. flask_exts-0.2.0/src/flask_exts/forms/form/session_csrf.py +31 -0
  46. flask_exts-0.2.0/src/flask_exts/forms/utils.py +32 -0
  47. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/widgets/recaptcha.py +1 -5
  48. flask_exts-0.2.0/src/flask_exts/forms/widgets/select.py +77 -0
  49. flask_exts-0.2.0/src/flask_exts/forms/widgets/xeditable.py +115 -0
  50. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/manager.py +6 -4
  51. flask_exts-0.2.0/src/flask_exts/static/admin/css/admin.css +110 -0
  52. flask_exts-0.2.0/src/flask_exts/static/admin/css/rediscli.css +48 -0
  53. flask_exts-0.2.0/src/flask_exts/static/admin/css/submenu.css +18 -0
  54. flask_exts-0.2.0/src/flask_exts/static/admin/js/actions.js +51 -0
  55. flask_exts-0.2.0/src/flask_exts/static/admin/js/bs4_filters.js +202 -0
  56. flask_exts-0.2.0/src/flask_exts/static/admin/js/details_filter.js +10 -0
  57. flask_exts-0.2.0/src/flask_exts/static/admin/js/filters.js +195 -0
  58. flask_exts-0.2.0/src/flask_exts/static/admin/js/form.js +667 -0
  59. flask_exts-0.2.0/src/flask_exts/static/admin/js/helpers.js +12 -0
  60. flask_exts-0.2.0/src/flask_exts/static/admin/js/modal.js +5 -0
  61. flask_exts-0.2.0/src/flask_exts/static/admin/js/rediscli.js +121 -0
  62. flask_exts-0.2.0/src/flask_exts/static/logo.png +0 -0
  63. flask_exts-0.2.0/src/flask_exts/static/vendor/jquery/jquery.min.js +2 -0
  64. flask_exts-0.2.0/src/flask_exts/template/__init__.py +35 -0
  65. flask_exts-0.2.0/src/flask_exts/template/theme.py +56 -0
  66. flask_exts-0.2.0/src/flask_exts/template/utils.py +61 -0
  67. flask_exts-0.2.0/src/flask_exts/templates/admin/actions.html +58 -0
  68. flask_exts-0.1.7/examples/admin/simple/templates/myadmin.html → flask_exts-0.2.0/src/flask_exts/templates/admin/admin.html +2 -1
  69. flask_exts-0.2.0/src/flask_exts/templates/admin/base.html +46 -0
  70. flask_exts-0.2.0/src/flask_exts/templates/admin/file/form.html +9 -0
  71. flask_exts-0.2.0/src/flask_exts/templates/admin/file/list.html +192 -0
  72. flask_exts-0.2.0/src/flask_exts/templates/admin/file/modals/form.html +13 -0
  73. flask_exts-0.2.0/src/flask_exts/templates/admin/index.html +6 -0
  74. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/admin/layout.html +27 -25
  75. flask_exts-0.2.0/src/flask_exts/templates/admin/lib.html +276 -0
  76. flask_exts-0.2.0/src/flask_exts/templates/admin/master.html +1 -0
  77. flask_exts-0.2.0/src/flask_exts/templates/admin/user/index.html +7 -0
  78. flask_exts-0.2.0/src/flask_exts/templates/admin/user/list.html +7 -0
  79. flask_exts-0.2.0/src/flask_exts/templates/admin/user/login.html +19 -0
  80. flask_exts-0.2.0/src/flask_exts/templates/admin/user/register.html +20 -0
  81. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/base.html +1 -2
  82. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/bootstrap4/form.html +2 -2
  83. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/bootstrap5/form.html +4 -4
  84. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/layout.html +6 -7
  85. flask_exts-0.2.0/src/flask_exts/templates/macro/form.html +16 -0
  86. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/macro/icon.html +1 -1
  87. flask_exts-0.2.0/src/flask_exts/templates/macro/message.html +17 -0
  88. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/macro/table.html +5 -4
  89. flask_exts-0.2.0/src/flask_exts/users/__init__.py +15 -0
  90. flask_exts-0.2.0/src/flask_exts/users/default_usercenter.py +51 -0
  91. flask_exts-0.2.0/src/flask_exts/users/forms/__init__.py +2 -0
  92. flask_exts-0.2.0/src/flask_exts/users/forms/login.py +6 -0
  93. flask_exts-0.2.0/src/flask_exts/users/forms/mixins.py +29 -0
  94. flask_exts-0.2.0/src/flask_exts/users/forms/profile.py +11 -0
  95. flask_exts-0.2.0/src/flask_exts/users/forms/register.py +6 -0
  96. flask_exts-0.2.0/src/flask_exts/users/usercenter.py +19 -0
  97. flask_exts-0.2.0/src/flask_exts/utils/__init__.py +9 -0
  98. flask_exts-0.2.0/tests/admin/fileadmin/test_fileadmin.py +238 -0
  99. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/admin/test_base.py +138 -152
  100. flask_exts-0.2.0/tests/admin/test_user_view.py +65 -0
  101. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/conftest.py +1 -6
  102. flask_exts-0.2.0/tests/forms/test_fields.py +76 -0
  103. flask_exts-0.2.0/tests/forms/test_form.py +37 -0
  104. flask_exts-0.1.7/tests/forms/test_upload_file.py → flask_exts-0.2.0/tests/forms/test_uploadfile.py +24 -17
  105. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/funcs.py +1 -1
  106. flask_exts-0.2.0/tests/template/bootstrap4/__init__.py +0 -0
  107. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_form.py +1 -1
  108. flask_exts-0.2.0/tests/template/bootstrap5/__init__.py +0 -0
  109. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap5/conftest.py +5 -4
  110. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap5/test_base.py +1 -2
  111. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap5/test_render_form.py +4 -4
  112. {flask_exts-0.1.7/tests/templating/element → flask_exts-0.2.0/tests/template/macros}/test_render_nav_item.py +0 -1
  113. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/test_base.py +3 -4
  114. flask_exts-0.2.0/tests/templates/mock.html +1 -0
  115. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/test_babel.py +18 -12
  116. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/test_base.py +5 -4
  117. flask_exts-0.1.7/docs/api.rst +0 -4
  118. flask_exts-0.1.7/docs/conf.py +0 -36
  119. flask_exts-0.1.7/docs/develop.rst +0 -46
  120. flask_exts-0.1.7/docs/fields.rst +0 -36
  121. flask_exts-0.1.7/docs/forms.rst +0 -9
  122. flask_exts-0.1.7/docs/requirements.txt +0 -3
  123. flask_exts-0.1.7/docs/templating.rst +0 -29
  124. flask_exts-0.1.7/examples/admin/simple/admin_app.py +0 -25
  125. flask_exts-0.1.7/examples/admin/simple/templates/admin/index.html +0 -22
  126. flask_exts-0.1.7/examples/admin/simple/templates/anotheradmin.html +0 -5
  127. flask_exts-0.1.7/examples/admin/simple/templates/test.html +0 -5
  128. flask_exts-0.1.7/examples/start/__init__.py +0 -1
  129. flask_exts-0.1.7/examples/start/make_app.py +0 -24
  130. flask_exts-0.1.7/examples/start/models/__init__.py +0 -24
  131. flask_exts-0.1.7/examples/start/register_blueprints.py +0 -36
  132. flask_exts-0.1.7/examples/start/templates/upload.html +0 -15
  133. flask_exts-0.1.7/examples/update-icons.py +0 -49
  134. flask_exts-0.1.7/requirements/develop.in +0 -1
  135. flask_exts-0.1.7/src/flask_exts/__about__.py +0 -1
  136. flask_exts-0.1.7/src/flask_exts/forms/__init__.py +0 -3
  137. flask_exts-0.1.7/src/flask_exts/forms/fields/__init__.py +0 -2
  138. flask_exts-0.1.7/src/flask_exts/forms/form/__init__.py +0 -2
  139. flask_exts-0.1.7/src/flask_exts/forms/form/base_form.py +0 -5
  140. flask_exts-0.1.7/src/flask_exts/forms/form/secure_form.py +0 -33
  141. flask_exts-0.1.7/src/flask_exts/forms/widgets/select.py +0 -26
  142. flask_exts-0.1.7/src/flask_exts/forms/widgets/template.py +0 -25
  143. flask_exts-0.1.7/src/flask_exts/static/vendor/jquery/jquery.slim.min.js +0 -2
  144. flask_exts-0.1.7/src/flask_exts/templates/admin/base.html +0 -41
  145. flask_exts-0.1.7/src/flask_exts/templates/admin/index.html +0 -2
  146. flask_exts-0.1.7/src/flask_exts/templates/admin/master.html +0 -1
  147. flask_exts-0.1.7/src/flask_exts/templates/demo.html +0 -7
  148. flask_exts-0.1.7/src/flask_exts/templates/macro/form.html +0 -5
  149. flask_exts-0.1.7/src/flask_exts/templating/__init__.py +0 -40
  150. flask_exts-0.1.7/src/flask_exts/templating/theme.py +0 -136
  151. flask_exts-0.1.7/src/flask_exts/utils/__init__.py +0 -4
  152. flask_exts-0.1.7/src/flask_exts/utils/csrf.py +0 -130
  153. flask_exts-0.1.7/src/flask_exts/utils/form.py +0 -63
  154. flask_exts-0.1.7/tests/forms/test_field_list.py +0 -41
  155. flask_exts-0.1.7/tests/forms/test_form.py +0 -59
  156. flask_exts-0.1.7/tests/templates/mock.html +0 -1
  157. flask_exts-0.1.7/tests/utils/test_csrf.py +0 -17
  158. {flask_exts-0.1.7 → flask_exts-0.2.0}/.github/workflows/release.yml +0 -0
  159. {flask_exts-0.1.7 → flask_exts-0.2.0}/.gitignore +0 -0
  160. {flask_exts-0.1.7 → flask_exts-0.2.0}/.readthedocs.yaml +0 -0
  161. {flask_exts-0.1.7 → flask_exts-0.2.0}/LICENSE.rst +0 -0
  162. {flask_exts-0.1.7 → flask_exts-0.2.0}/README.rst +0 -0
  163. {flask_exts-0.1.7 → flask_exts-0.2.0}/babel/babel.cfg +0 -0
  164. {flask_exts-0.1.7 → flask_exts-0.2.0}/babel/babel.sh +0 -0
  165. {flask_exts-0.1.7 → flask_exts-0.2.0}/babel/crowdin_pull.sh +0 -0
  166. {flask_exts-0.1.7 → flask_exts-0.2.0}/babel/crowdin_push.sh +0 -0
  167. {flask_exts-0.1.7 → flask_exts-0.2.0}/babel/messages.pot +0 -0
  168. {flask_exts-0.1.7 → flask_exts-0.2.0}/docs/Makefile +0 -0
  169. {flask_exts-0.1.7/src/flask_exts/static → flask_exts-0.2.0/docs/_static}/logo.png +0 -0
  170. {flask_exts-0.1.7 → flask_exts-0.2.0}/docs/changes.rst +0 -0
  171. {flask_exts-0.1.7 → flask_exts-0.2.0}/docs/examples.rst +0 -0
  172. {flask_exts-0.1.7 → flask_exts-0.2.0}/docs/make.bat +0 -0
  173. {flask_exts-0.1.7/examples/admin/simple → flask_exts-0.2.0/examples/admin/fileadmin}/__init__.py +0 -0
  174. {flask_exts-0.1.7/examples/admin/simple → flask_exts-0.2.0/examples/admin/fileadmin}/make_app.py +0 -0
  175. /flask_exts-0.1.7/src/flask_exts/forms/widgets/__init__.py → /flask_exts-0.2.0/examples/admin/fileadmin/tmp/bbb/a.txt +0 -0
  176. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/static/favicon.ico +0 -0
  177. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/bootswatch.html +0 -0
  178. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/flash.html +0 -0
  179. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/form.html +0 -0
  180. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/icon.html +0 -0
  181. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/icons.html +0 -0
  182. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/index.html +0 -0
  183. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/nav.html +0 -0
  184. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/pagination.html +0 -0
  185. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap4/templates/table.html +0 -0
  186. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/static/favicon.ico +0 -0
  187. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/bootswatch.html +0 -0
  188. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/flash.html +0 -0
  189. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/form.html +0 -0
  190. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/icon.html +0 -0
  191. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/icons.html +0 -0
  192. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/index.html +0 -0
  193. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/nav.html +0 -0
  194. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/pagination.html +0 -0
  195. {flask_exts-0.1.7 → flask_exts-0.2.0}/examples/bootstrap5/templates/table.html +0 -0
  196. {flask_exts-0.1.7 → flask_exts-0.2.0}/requirements/build.in +0 -0
  197. {flask_exts-0.1.7 → flask_exts-0.2.0}/requirements/test.in +0 -0
  198. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/__init__.py +0 -0
  199. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/admin/__init__.py +0 -0
  200. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/admin/wraps.py +0 -0
  201. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/babel/__init__.py +0 -0
  202. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/babel/selector.py +0 -0
  203. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/file.py +0 -0
  204. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/json.py +0 -0
  205. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/recaptcha.py +0 -0
  206. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/fields/switch.py +0 -0
  207. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/rules.py +0 -0
  208. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/validators/__init__.py +0 -0
  209. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/validators/field_list.py +0 -0
  210. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/validators/file.py +0 -0
  211. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/validators/recaptcha.py +0 -0
  212. {flask_exts-0.1.7/src/flask_exts/plugins → flask_exts-0.2.0/src/flask_exts/forms/widgets}/__init__.py +0 -0
  213. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/widgets/datetime.py +0 -0
  214. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/forms/widgets/file.py +0 -0
  215. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/static/vendor/bootstrap-icons/bootstrap-icons.svg +0 -0
  216. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/static/vendor/bootstrap4/bootstrap.bundle.min.js +0 -0
  217. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/static/vendor/bootstrap4/bootstrap.min.css +0 -0
  218. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/static/vendor/bootstrap5/bootstrap.bundle.min.js +0 -0
  219. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/static/vendor/bootstrap5/bootstrap.min.css +0 -0
  220. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/bootstrap4/message.html +0 -0
  221. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/bootstrap5/message.html +0 -0
  222. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/macro/nav.html +0 -0
  223. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/macro/pagination.html +0 -0
  224. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/templates/macro/static.html +0 -0
  225. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/translations/__init__.py +0 -0
  226. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/translations/en/LC_MESSAGES/messages.mo +0 -0
  227. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/translations/en/LC_MESSAGES/messages.po +0 -0
  228. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/translations/zh_CN/LC_MESSAGES/messages.mo +0 -0
  229. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/translations/zh_CN/LC_MESSAGES/messages.po +0 -0
  230. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/utils/g.py +0 -0
  231. {flask_exts-0.1.7 → flask_exts-0.2.0}/src/flask_exts/utils/url.py +0 -0
  232. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/__init__.py +0 -0
  233. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/admin/__init__.py +0 -0
  234. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/admin/fileadmin}/__init__.py +0 -0
  235. /flask_exts-0.1.7/tests/templating/bootstrap4/__init__.py → /flask_exts-0.2.0/tests/admin/fileadmin/files/dummy.txt +0 -0
  236. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/data/copyleft.gif +0 -0
  237. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/data/copyleft.jpeg +0 -0
  238. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/data/copyleft.jpg +0 -0
  239. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/data/copyleft.png +0 -0
  240. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/data/copyleft.tiff +0 -0
  241. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/forms/test_filefield.py +0 -0
  242. {flask_exts-0.1.7/tests/templating/bootstrap5 → flask_exts-0.2.0/tests/template}/__init__.py +0 -0
  243. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/conftest.py +0 -0
  244. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_field.py +0 -0
  245. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_form_row.py +0 -0
  246. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_hidden_errors.py +0 -0
  247. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_icon.py +0 -0
  248. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_messages.py +0 -0
  249. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_pager.py +0 -0
  250. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_pagination.py +0 -0
  251. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap4/test_render_table.py +0 -0
  252. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap5/test_pagination.py +0 -0
  253. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap5/test_render_form_row.py +0 -0
  254. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/bootstrap5/test_render_messages.py +0 -0
  255. {flask_exts-0.1.7/tests/templating → flask_exts-0.2.0/tests/template}/conftest.py +0 -0
  256. {flask_exts-0.1.7/tests/templating/element → flask_exts-0.2.0/tests/template/macros}/test_render_breadcrumb_item.py +0 -0
  257. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/templates/method.html +0 -0
  258. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/translations/en/LC_MESSAGES/messages.mo +0 -0
  259. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/translations/en/LC_MESSAGES/messages.po +0 -0
  260. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/translations/messages.pot +0 -0
  261. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/translations/zh_CN/LC_MESSAGES/messages.mo +0 -0
  262. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/translations/zh_CN/LC_MESSAGES/messages.po +0 -0
  263. {flask_exts-0.1.7 → flask_exts-0.2.0}/tests/utils/test_url.py +0 -0
@@ -1,9 +1,30 @@
1
+ v0.2.0
2
+ ------
3
+
4
+ Released 2025-01-07
5
+
6
+ - update templates.macros
7
+
8
+ v0.1.9
9
+ ------
10
+
11
+ Released 2024-12-01
12
+
13
+ - add index_view
14
+
15
+ v0.1.8
16
+ ------
17
+
18
+ Released 2024-11-24
19
+
20
+ - add user_view
21
+
1
22
  v0.1.7
2
23
  ------
3
24
 
4
25
  Released 2024-10-13
5
26
 
6
- - add theme for templating
27
+ - add theme for template
7
28
  - admin view framework
8
29
 
9
30
  v0.1.6
@@ -14,7 +35,6 @@ Released 2024-09-14
14
35
  - merge translations of wtforms, flask_exts and app into flask_babel.get_translations()
15
36
  - update FileField and ImageField
16
37
  - add url for template.static
17
- - use namespace ns.bootstrap to control bootstrap's css and js
18
38
 
19
39
  v0.1.5
20
40
  ------
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: Flask-Exts
3
- Version: 0.1.7
3
+ Version: 0.2.0
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
@@ -42,6 +42,7 @@ Classifier: Programming Language :: Python :: 3.11
42
42
  Classifier: Topic :: Software Development :: Build Tools
43
43
  Requires-Python: >=3.10
44
44
  Requires-Dist: flask-babel>=4.0
45
+ Requires-Dist: flask-login>=0.6
45
46
  Requires-Dist: flask-sqlalchemy>=3.0
46
47
  Requires-Dist: flask>=3.0
47
48
  Requires-Dist: wtforms>=3.0
@@ -0,0 +1,62 @@
1
+ # Configuration file for the Sphinx documentation builder.
2
+ #
3
+ # This file only contains a selection of the most common options. For a full
4
+ # list see the documentation:
5
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html
6
+
7
+ # -- Path setup --------------------------------------------------------------
8
+
9
+ # If extensions (or modules to document with autodoc) are in another directory,
10
+ # add these directories to sys.path here. If the directory is relative to the
11
+ # documentation root, use os.path.abspath to make it absolute, like shown here.
12
+ #
13
+ # import os
14
+ # import sys
15
+ # sys.path.insert(0, os.path.abspath('.'))
16
+
17
+
18
+ # -- Project information -----------------------------------------------------
19
+
20
+ project = 'Flask-Exts'
21
+ copyright = '2024, David Dong Hua'
22
+ author = 'David Dong Hua'
23
+
24
+ # -- General configuration ---------------------------------------------------
25
+ # -- General configuration
26
+
27
+ extensions = [
28
+ "sphinx.ext.duration",
29
+ "sphinx.ext.doctest",
30
+ "sphinx.ext.autodoc",
31
+ "sphinx.ext.autosummary",
32
+ "sphinx.ext.intersphinx",
33
+ ]
34
+
35
+ intersphinx_mapping = {
36
+ "rtd": ("https://docs.readthedocs.io/en/stable/", None),
37
+ "python": ("https://docs.python.org/3/", None),
38
+ "sphinx": ("https://www.sphinx-doc.org/en/master/", None),
39
+ }
40
+ intersphinx_disabled_domains = ["std"]
41
+
42
+ templates_path = ["_templates"]
43
+
44
+ # -- Options for EPUB output
45
+ epub_show_urls = "footnote"
46
+
47
+ # List of patterns, relative to source directory, that match files and
48
+ # directories to ignore when looking for source files.
49
+ # This pattern also affects html_static_path and html_extra_path.
50
+ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
51
+
52
+ # -- Options for HTML output -------------------------------------------------
53
+
54
+ # The theme to use for HTML and HTML Help pages. See the documentation for
55
+ # a list of builtin themes.
56
+ #
57
+ html_theme = "sphinx_rtd_theme"
58
+
59
+ # Add any paths that contain custom static files (such as style sheets) here,
60
+ # relative to this directory. They are copied after the builtin static files,
61
+ # so a file named "default.css" will overwrite the builtin "default.css".
62
+ html_static_path = ["_static"]
@@ -1,17 +1,6 @@
1
- =====
2
- Usage
3
- =====
4
-
5
- .. _installation:
6
-
7
- Installation
8
- ==============
9
-
10
- To use Flask-Exts, first install it using pip:
11
-
12
- .. code-block:: console
13
-
14
- (.venv) $ pip install flask-exts
1
+ ==========
2
+ Configure
3
+ ==========
15
4
 
16
5
  Configuration
17
6
  ==============
@@ -23,38 +12,23 @@ Configuration
23
12
  Default is ``None``.
24
13
  ``BABEL_DEFAULT_TIMEZONE`` Set to ``Asia/Shanghai`` to babel's default timezone.
25
14
  Default is ``None``.
26
- ``TEMPLATE_ENABLED`` Set to ``False`` to disable templating extension.
15
+ ``CSRF_ENABLED`` Set to ``False`` to enable form's CSRF .
27
16
  Default is ``True``.
28
- ``TEMPLATE_THEME`` Set to ``theme`` to create custom theme
29
- Default is ``templating.theme.DefaultTheme()``
30
- ``JQUERY_JS_URL`` Set to ``jquery js url`` to active ``jquery``.
31
- Default is in ``jsdelivr``.
32
- ``BOOTSTRAP_CSS_URL`` Set to ``bootstrap css url`` to active ``bootstrap css``.
33
- Default is in ``jsdelivr``.
34
- ``BOOTSTRAP_JS_URL`` Set to ``bootstrap js url`` to active ``bootstrap js``.
35
- Default is in ``jsdelivr``.
36
- ``ICON_SPRITE_URL`` Set to ``icon url`` to active ``icon``.
37
- Default is in ``/template/static/vendor/bootstrap-icons/bootstrap-icons.svg``.
38
- ``CSRF_ENABLED`` Set to ``True`` to enable form's CSRF .
39
- Default is ``False``.
40
17
  ``CSRF_SECRET_KEY`` Random data for generating secure tokens.
41
18
  If this is not set then ``SECRET_KEY`` is used.
42
19
  ``CSRF_FIELD_NAME`` Name of the form field and session key that holds the CSRF token.
43
20
  Default is ``csrf_token``.
44
21
  ``CSRF_TIME_LIMIT`` Max age in seconds for CSRF tokens.
45
22
  Default is ``1800``.
23
+ ``TEMPLATE_ENABLED`` Set to ``False`` to disable templating extension.
24
+ Default is ``True``.
25
+ ``TEMPLATE_THEME`` Set to ``theme`` to create custom theme
26
+ Default is ``template.theme.BootstrapTheme(4)``
27
+ ``USER_ENABLED`` Set to ``False`` to disable ``User`` support.
28
+ Default is ``True``.
29
+ ``USER_CENTER`` set to ``user center`` to create custom user_center
30
+ Default is ``users.user_center.DefaultUserCenter()``
31
+ ``FLASK_LOGIN_ENABLED`` Set to ``False`` to disable ``Flask-Login``.
32
+ Default is ``True``.
46
33
  ========================== =====================================================================
47
34
 
48
- Start
49
- ======
50
-
51
- .. code-block:: python
52
-
53
- from flask_exts import Manager
54
- from flask import Flask
55
-
56
- manager = Manager()
57
- app = Flask(__name__)
58
-
59
- # init Manager
60
- manager.init_app(app)
@@ -1,10 +1,56 @@
1
- Translations
2
- ============
1
+ =======
2
+ Develop
3
+ =======
3
4
 
4
- src
5
- ---
5
+ Install
6
+ =======
6
7
 
7
- pybabel::
8
+ .. code-block:: console
9
+
10
+ $ pip install -e .
11
+ $ pip install -r requirements/develop.in
12
+
13
+ Test
14
+ ====
15
+ Tests are run with `pytest <https://pytest.org/>`_.
16
+ To run the tests, from the project directory:
17
+
18
+ .. code-block:: console
19
+
20
+ # requirements
21
+ $ pip install -r requirements/test.in
22
+
23
+ # update translation
24
+ $ pybabel compile -d src/flask_exts/translations -D messages
25
+ $ pybabel compile -d tests/translations
26
+
27
+ # test
28
+ $ pytest
29
+
30
+ Docs
31
+ ====
32
+
33
+ .. code-block:: console
34
+
35
+ $ pip install -r docs/requirements.txt
36
+ $ cd docs
37
+ $ make html
38
+
39
+ Publish
40
+ =======
41
+
42
+ .. code-block:: console
43
+
44
+ $ pip install -r requirements/build.in
45
+ $ python -m build
46
+
47
+ Translation
48
+ =============
49
+
50
+ pybabel
51
+ -------------
52
+
53
+ .. code-block:: console
8
54
 
9
55
  # extract messages from source files and generate a POT file
10
56
  pybabel extract -F babel.cfg -o babel/messages.pot src/
@@ -27,7 +73,7 @@ pybabel::
27
73
  tests
28
74
  -----
29
75
 
30
- pybabel::
76
+ .. code-block:: console
31
77
 
32
78
 
33
79
  cd tests/
@@ -47,9 +93,4 @@ pybabel::
47
93
 
48
94
  # compile message catalogs to MO files
49
95
 
50
- pybabel compile -d translations
51
-
52
-
53
-
54
-
55
-
96
+ pybabel compile -d translations
@@ -8,16 +8,33 @@ Welcome to Flask-Exts's documentation!
8
8
 
9
9
  **Flask-Exts** is a Flask extensions with admin, SQLAlchemy, babel, forms, fields, widgets, and so on.
10
10
 
11
+ .. _installation:
12
+
13
+ Installation
14
+ ==============
15
+
16
+ To use Flask-Exts, first install it using pip:
17
+
18
+ .. code-block:: console
19
+
20
+ (.venv) $ pip install flask-exts
21
+
22
+ Examples
23
+ ===========
24
+
25
+ ``python simple.py`` to run a simple example.
26
+
27
+ .. literalinclude:: ../examples/simple.py
28
+ :language: python
29
+
30
+ More examples, please click :doc:`examples`.
31
+
11
32
  .. toctree::
12
33
  :maxdepth: 2
13
34
  :caption: Contents:
14
35
 
15
- usage
16
- api
17
- forms
18
- templating
36
+ configure
19
37
  develop
20
- translation
21
38
  examples
22
39
  changes
23
40
 
@@ -0,0 +1,2 @@
1
+ sphinx
2
+ sphinx_rtd_theme
@@ -2,7 +2,7 @@
2
2
  Examples
3
3
  ========================
4
4
 
5
- Install
5
+ Download
6
6
  =========
7
7
 
8
8
  Type these commands in the terminal:
@@ -14,50 +14,50 @@ Type these commands in the terminal:
14
14
  $ python3 -m venv venv
15
15
  $ source venv/bin/activate
16
16
  $ pip install flask-exts
17
-
18
17
 
19
- Run the demo applications
20
- ==========================
18
+ Run the examples
19
+ ===============================
21
20
 
22
- Type the command in the terminal:
21
+ Type the command in the terminal, then go to http://localhost:5000.
23
22
 
24
- .. code-block:: bash
23
+ Start
24
+ ----------
25
25
 
26
- $ flask --app start run --debug --port=5000
26
+ simple
27
+ ---------
27
28
 
28
- Bootstrap 4
29
- -----------------
29
+ run only one file.
30
30
 
31
31
  .. code-block:: bash
32
32
 
33
- $ flask --app bootstrap4/app.py run
33
+ $ python simple.py
34
34
 
35
- Bootstrap 5
35
+ demo
36
36
  -----------------
37
37
 
38
+ With sqlite db.
39
+
38
40
  .. code-block:: bash
39
41
 
40
- $ flask --app bootstrap5/app.py run
41
-
42
- Now go to http://localhost:5000.
42
+ $ flask --app demo run --debug --port=5000
43
43
 
44
- admin
44
+ Bootstrap 4
45
45
  -----------------
46
46
 
47
47
  .. code-block:: bash
48
-
49
- $ flask --app admin/simple run
50
-
51
- Now go to http://localhost:5000.
52
48
 
49
+ $ flask --app bootstrap4/app.py run
53
50
 
54
- Overview of icons
51
+ Bootstrap 5
55
52
  -----------------
56
53
 
57
- When Bootstrap-Flask updates the icon file, the overview page can be upgraded with:
58
-
59
-
60
54
  .. code-block:: bash
55
+
56
+ $ flask --app bootstrap5/app.py run
61
57
 
62
- $ python3 update-icons.py
58
+ fileadmin
59
+ -----------------
63
60
 
61
+ .. code-block:: bash
62
+
63
+ $ flask --app admin/fileadmin run
@@ -0,0 +1,17 @@
1
+ import os.path as op
2
+ from flask_exts.admin import Admin
3
+ from flask_exts.admin.file_admin import LocalFileAdmin
4
+
5
+ class FileAdmin(LocalFileAdmin):
6
+ upload_modal = True
7
+ rename_modal = True
8
+
9
+ # Create admin interface
10
+ admin = Admin(name="Example: File Admin Views")
11
+
12
+ # Create file admin view
13
+ path = op.join(op.dirname(__file__), "tmp")
14
+ file_admin_view = FileAdmin(path, name="TmpFiles")
15
+ # file_admin_view.rename_modal=True
16
+
17
+ admin.add_view(file_admin_view)
@@ -6,7 +6,7 @@ from wtforms.validators import DataRequired, Length, Regexp
6
6
  from wtforms.fields import *
7
7
  from flask_sqlalchemy import SQLAlchemy
8
8
  from flask_exts.forms.form import FlaskForm
9
- from flask_exts.forms.fields.switch import SwitchField
9
+ from flask_exts.forms.fields import SwitchField
10
10
  from flask_exts import Manager
11
11
 
12
12
  manager = Manager()
@@ -32,7 +32,7 @@ class ExampleForm(FlaskForm):
32
32
  email = EmailField()
33
33
  url = URLField()
34
34
  telephone = TelField()
35
- image = FileField(render_kw={'class': 'my-class'}, validators=[Regexp('.+\.jpg$')]) # add your class
35
+ image = FileField(render_kw={'class': 'my-class'}, validators=[Regexp(r'.+\.jpg$')]) # add your class
36
36
  option = RadioField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])
37
37
  select = SelectField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])
38
38
  select_multiple = SelectMultipleField(choices=[('dog', 'Dog'), ('cat', 'Cat'), ('bird', 'Bird'), ('alien', 'Alien')])
@@ -6,6 +6,7 @@
6
6
  {% block title %}Flask-Exts Bootstrap 4 Demo Application{% endblock %}
7
7
 
8
8
  {% block styles %}
9
+ {{ super() }}
9
10
  <style>
10
11
  pre {
11
12
  background: #ddd;
@@ -7,11 +7,11 @@ from wtforms.fields import *
7
7
  from flask_sqlalchemy import SQLAlchemy
8
8
 
9
9
  from flask_exts.forms.form import FlaskForm
10
- from flask_exts.forms.fields.switch import SwitchField
10
+ from flask_exts.forms.fields import SwitchField
11
11
  from flask_exts import Manager
12
- from flask_exts.templating.theme import DefaultTheme
12
+ from flask_exts.template.theme import BootstrapTheme
13
13
 
14
- theme = DefaultTheme(bootstrap_version=5)
14
+ theme = BootstrapTheme(version=5)
15
15
 
16
16
  manager = Manager()
17
17
  app = Flask(__name__)
@@ -47,7 +47,7 @@ class ExampleForm(FlaskForm):
47
47
  url = URLField()
48
48
  telephone = TelField()
49
49
  image = FileField(
50
- render_kw={"class": "my-class"}, validators=[Regexp(".+\.jpg$")]
50
+ render_kw={"class": "my-class"}, validators=[Regexp(r".+\.jpg$")]
51
51
  ) # add your class
52
52
  option = RadioField(
53
53
  choices=[("dog", "Dog"), ("cat", "Cat"), ("bird", "Bird"), ("alien", "Alien")]
@@ -6,6 +6,7 @@
6
6
  {% block title %}Flask-Exts Bootstrap 5 Demo Application{% endblock %}
7
7
 
8
8
  {% block styles %}
9
+ {{ super() }}
9
10
  <style>
10
11
  pre {
11
12
  background: #ddd;
@@ -0,0 +1 @@
1
+ from .make_app import create_app
@@ -0,0 +1,52 @@
1
+ import os.path
2
+ from flask import Flask
3
+ from flask_exts import Manager
4
+ from flask_exts.admin import Admin
5
+ from .models import db
6
+ from .user_center import UserCenter
7
+ from .views.my_view import myview
8
+
9
+
10
+ def get_sqlite_path():
11
+ app_dir = os.path.realpath(os.path.dirname(__file__))
12
+ database_path = os.path.join(app_dir, "sample.sqlite")
13
+ return database_path
14
+
15
+
16
+ def build_sample_db(app):
17
+ # db.drop_all()
18
+ db.create_all()
19
+ user_center = app.config["USER_CENTER"]
20
+ user_center.register_user("admin", "admin", "admin@example.com")
21
+
22
+
23
+ def create_app():
24
+ app = Flask(__name__)
25
+ app.config["SECRET_KEY"] = "dev"
26
+ # app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
27
+ app.config["DATABASE_FILE"] = get_sqlite_path()
28
+ app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + app.config["DATABASE_FILE"]
29
+
30
+ app.config["USER_CENTER"] = UserCenter()
31
+
32
+ init_app(app)
33
+
34
+ return app
35
+
36
+
37
+ def init_app(app: Flask):
38
+ from .models import init_db
39
+
40
+ init_db(app)
41
+
42
+ manager = Manager()
43
+ manager.init_app(app)
44
+
45
+ admin = Admin(name="Demo")
46
+ admin.init_app(app)
47
+ admin.add_view(myview)
48
+
49
+ if not os.path.exists(app.config["DATABASE_FILE"]):
50
+ with app.app_context():
51
+ build_sample_db(app)
52
+
@@ -0,0 +1,16 @@
1
+ from flask_sqlalchemy import SQLAlchemy
2
+ from sqlalchemy.orm import DeclarativeBase
3
+ from sqlalchemy import select
4
+
5
+
6
+ class Base(DeclarativeBase):
7
+ pass
8
+
9
+
10
+ db = SQLAlchemy(model_class=Base)
11
+
12
+
13
+ def init_db(app):
14
+ db.init_app(app)
15
+
16
+ from . import user
@@ -0,0 +1,16 @@
1
+ from datetime import datetime
2
+ from sqlalchemy.orm import Mapped
3
+ from sqlalchemy.orm import mapped_column
4
+ from flask_login import UserMixin
5
+ from . import db
6
+
7
+
8
+ class User(db.Model, UserMixin):
9
+ id: Mapped[int] = mapped_column(primary_key=True)
10
+ username: Mapped[str]
11
+ email: Mapped[str]
12
+ password: Mapped[str]
13
+ created_at: Mapped[datetime] = mapped_column(default=datetime.now)
14
+ updated_at: Mapped[datetime] = mapped_column(
15
+ default=datetime.now, onupdate=datetime.now
16
+ )
@@ -0,0 +1,6 @@
1
+ {% extends 'admin/master.html' %}
2
+ {% block main %}
3
+ <div>
4
+ Demo:my:index
5
+ </div>
6
+ {% endblock %}
@@ -0,0 +1,54 @@
1
+ from werkzeug.security import generate_password_hash, check_password_hash
2
+ from flask_exts.users.default_usercenter import DefaultUserCenter
3
+ from .models import db,select
4
+ from .models.user import User
5
+
6
+ class UserCenter(DefaultUserCenter):
7
+ user_class = User
8
+
9
+ def __init__(self):
10
+ self.users = []
11
+
12
+ def user_loader(self, user_id):
13
+ user = db.session.get(User, int(user_id))
14
+ return user
15
+
16
+ def get_users(self):
17
+ stmt = select(User).order_by("id")
18
+ users = db.session.execute(stmt).scalars()
19
+ return users
20
+
21
+ def get_user_by_id(self, id):
22
+ user = db.session.get(User, id)
23
+ return user
24
+
25
+ def login_user_by_username_password(self, username, password):
26
+ stmt = select(User).filter_by(username=username)
27
+ user = db.session.execute(stmt).scalar()
28
+ if user is None:
29
+ return (None, "invalid username")
30
+ elif not check_password_hash(user.password, password):
31
+ return (None, "invalid password")
32
+ else:
33
+ return (user, None)
34
+
35
+ def register_user(self, username, password, email):
36
+ stmt_filter_username = select(User).filter_by(username=username)
37
+ user_filter_username = db.session.execute(stmt_filter_username).scalar()
38
+ if user_filter_username is not None:
39
+ return (None, "invalid username")
40
+
41
+ stmt_filter_email = select(User).filter_by(email=email)
42
+ user_filter_email = db.session.execute(stmt_filter_email).scalar()
43
+ if user_filter_email is not None:
44
+ return (None, "invalid email")
45
+
46
+ user = self.user_class(username=username)
47
+ user.password = generate_password_hash(password)
48
+ user.email = email
49
+ db.session.add(user)
50
+ db.session.commit()
51
+ return (user, None)
52
+
53
+ def remove_user(self, user_id):
54
+ return NotImplemented
@@ -0,0 +1,10 @@
1
+ from flask_exts.admin import expose
2
+ from flask_exts.admin import BaseView
3
+
4
+
5
+ class MyView(BaseView):
6
+ @expose("/")
7
+ def index(self):
8
+ return self.render("my/index.html")
9
+
10
+ myview = MyView(name="MyView")
@@ -0,0 +1,17 @@
1
+ # simple.py
2
+
3
+ from flask import Flask
4
+ from flask_exts import Manager
5
+ from flask_exts.admin import Admin
6
+
7
+ app = Flask(__name__)
8
+ app.config["SECRET_KEY"] = "dev"
9
+ # Manager init
10
+ manager = Manager()
11
+ manager.init_app(app)
12
+ # Admin init for index_view and user_view
13
+ admin = Admin()
14
+ admin.init_app(app)
15
+
16
+ if __name__ == "__main__":
17
+ app.run(debug=True)
@@ -30,6 +30,7 @@ dependencies = [
30
30
  "WTForms>=3.0",
31
31
  "flask-babel>=4.0",
32
32
  "Flask-SQLAlchemy>=3.0",
33
+ "Flask-Login>=0.6",
33
34
  ]
34
35
 
35
36
  [project.urls]
@@ -0,0 +1 @@
1
+ __version__ = "0.2.0"