From 5a4a6a77331b26307f3fc0607db551ac23d72d3f Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Thu, 14 Nov 2024 03:59:32 +0000 Subject: [PATCH 1/7] Added extra_css and extra_js to BaseView --- .gitignore | 1 + README.md | 7 ++++++- examples/sqla/app.py | 3 +++ flask_admin/base.py | 4 ++++ pyproject.toml | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 243c83924..9fbfd37c6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ flask_admin/tests/tmp dist/* make.bat venv +.venv *.sublime-* .coverage __pycache__ diff --git a/README.md b/README.md index f5f23aaf0..375d22146 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ should be included, feel free to make the changes and submit a *pull-request*. To build the docs in your local environment, from the project directory: - tox -e docs-html + tox -e docs ## Installation @@ -113,6 +113,11 @@ by doing: cd flask-admin pip install . +If you are contributing a bug fix or a new feature, you can install the app in editable mode: + + + pip install -e . + ## Tests Tests are run with *pytest*. If you are not familiar with this package, you can find out more on [their website](https://pytest.org/). diff --git a/examples/sqla/app.py b/examples/sqla/app.py index 54aa23430..0e50d33fe 100644 --- a/examples/sqla/app.py +++ b/examples/sqla/app.py @@ -1,6 +1,8 @@ import os import os.path as op +from jinja2 import StrictUndefined + from admin import app from admin.data import build_sample_db @@ -13,4 +15,5 @@ if __name__ == "__main__": # Start app + app.jinja_env.undefined = StrictUndefined app.run(debug=True) diff --git a/flask_admin/base.py b/flask_admin/base.py index 760b73fe0..3faed9d1e 100644 --- a/flask_admin/base.py +++ b/flask_admin/base.py @@ -146,6 +146,10 @@ def index(self): ) """ + extra_css: list[str] = [] + + extra_js: list[str] = [] + @property def _template_args(self): """ diff --git a/pyproject.toml b/pyproject.toml index 1366397db..3a76e0180 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,7 @@ build-backend = "flit_core.buildapi" name = "flask_admin" [tool.pytest.ini_options] -testpaths = ["tests"] +testpaths = ["flask_admin/tests"] markers = [ "flask_babel: requires Flask-Babel to be installed" ] From 6e5b16c4b7357788f2fbbe05c2813299b08128ac Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Thu, 14 Nov 2024 04:21:47 +0000 Subject: [PATCH 2/7] Fix more parts for PR --- doc/changelog.rst | 7 +++++++ flask_admin/base.py | 2 ++ flask_admin/tests/fileadmin/files/dummy.txt | 2 +- flask_admin/tests/test_base.py | 5 ++--- requirements-skip/tests-min.txt | 2 -- requirements/dev.txt | 4 ---- requirements/typing.txt | 2 -- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/changelog.rst b/doc/changelog.rst index 526a694a8..4feace7a2 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -1,6 +1,13 @@ Changelog ========= +2.0.0a3 +------- + +Fixes: + +* Jinja templates can now be loaded in StrictUndefined mode. + 2.0.0a2 ------- diff --git a/flask_admin/base.py b/flask_admin/base.py index 3faed9d1e..e07d7d966 100644 --- a/flask_admin/base.py +++ b/flask_admin/base.py @@ -147,8 +147,10 @@ def index(self): """ extra_css: list[str] = [] + """Extra CSS files to include in the page""" extra_js: list[str] = [] + """Extra JavaScript files to include in the page""" @property def _template_args(self): diff --git a/flask_admin/tests/fileadmin/files/dummy.txt b/flask_admin/tests/fileadmin/files/dummy.txt index 7a4392a29..d8afd1ed3 100644 --- a/flask_admin/tests/fileadmin/files/dummy.txt +++ b/flask_admin/tests/fileadmin/files/dummy.txt @@ -1 +1 @@ -new_string +new_string \ No newline at end of file diff --git a/flask_admin/tests/test_base.py b/flask_admin/tests/test_base.py index 7f6d60d0c..47da01611 100644 --- a/flask_admin/tests/test_base.py +++ b/flask_admin/tests/test_base.py @@ -6,6 +6,7 @@ from flask import request from flask import url_for from flask.views import MethodView +from jinja2 import StrictUndefined from flask_admin import base @@ -18,10 +19,9 @@ def app(): app = Flask(__name__) app.config["SECRET_KEY"] = "1" app.config["WTF_CSRF_ENABLED"] = False - + app.jinja_env.undefined = StrictUndefined yield app - class MockView(base.BaseView): # Various properties allow_call = True @@ -444,7 +444,6 @@ def test_add_links(app, admin): assert "TestMenuLink1" in data assert "TestMenuLink2" in data - def check_class_name(): view = MockView() assert view.name == "Mock View" diff --git a/requirements-skip/tests-min.txt b/requirements-skip/tests-min.txt index 267e66593..bc5126080 100644 --- a/requirements-skip/tests-min.txt +++ b/requirements-skip/tests-min.txt @@ -102,8 +102,6 @@ mccabe==0.7.0 # pylint moto==5.0.18 # via -r tests-min.in -numpy==1.24.4 - # via shapely packaging==24.1 # via # geoalchemy2 diff --git a/requirements/dev.txt b/requirements/dev.txt index a4b4a85d0..068c6c967 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -167,10 +167,6 @@ nodeenv==1.9.1 # -r typing.txt # pre-commit # pyright -numpy==1.24.4 - # via - # -r typing.txt - # types-shapely packaging==24.1 # via # -r docs.txt diff --git a/requirements/typing.txt b/requirements/typing.txt index 49e0ec0de..f166f92a9 100644 --- a/requirements/typing.txt +++ b/requirements/typing.txt @@ -65,8 +65,6 @@ mypy-extensions==1.0.0 # via mypy nodeenv==1.9.1 # via pyright -numpy==1.24.4 - # via types-shapely packaging==24.1 # via pytest platformdirs==4.2.2 From 4884a37247165b94cef6fb0724af6742305d80e7 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Fri, 15 Nov 2024 22:55:55 +0000 Subject: [PATCH 3/7] Revert unrelated changes --- .gitignore | 1 - README.md | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 9fbfd37c6..243c83924 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,6 @@ flask_admin/tests/tmp dist/* make.bat venv -.venv *.sublime-* .coverage __pycache__ diff --git a/README.md b/README.md index 375d22146..f5f23aaf0 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ should be included, feel free to make the changes and submit a *pull-request*. To build the docs in your local environment, from the project directory: - tox -e docs + tox -e docs-html ## Installation @@ -113,11 +113,6 @@ by doing: cd flask-admin pip install . -If you are contributing a bug fix or a new feature, you can install the app in editable mode: - - - pip install -e . - ## Tests Tests are run with *pytest*. If you are not familiar with this package, you can find out more on [their website](https://pytest.org/). From 19de39c94fd16fff750d8367dc5a0196225fd3cc Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Fri, 15 Nov 2024 22:57:16 +0000 Subject: [PATCH 4/7] Revert unrelated changes --- flask_admin/tests/fileadmin/files/dummy.txt | 2 +- pyproject.toml | 2 +- requirements-skip/tests-min.txt | 2 ++ requirements/dev.txt | 4 ++++ requirements/typing.txt | 2 ++ 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/flask_admin/tests/fileadmin/files/dummy.txt b/flask_admin/tests/fileadmin/files/dummy.txt index d8afd1ed3..7a4392a29 100644 --- a/flask_admin/tests/fileadmin/files/dummy.txt +++ b/flask_admin/tests/fileadmin/files/dummy.txt @@ -1 +1 @@ -new_string \ No newline at end of file +new_string diff --git a/pyproject.toml b/pyproject.toml index 3a76e0180..1366397db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,7 @@ build-backend = "flit_core.buildapi" name = "flask_admin" [tool.pytest.ini_options] -testpaths = ["flask_admin/tests"] +testpaths = ["tests"] markers = [ "flask_babel: requires Flask-Babel to be installed" ] diff --git a/requirements-skip/tests-min.txt b/requirements-skip/tests-min.txt index bc5126080..267e66593 100644 --- a/requirements-skip/tests-min.txt +++ b/requirements-skip/tests-min.txt @@ -102,6 +102,8 @@ mccabe==0.7.0 # pylint moto==5.0.18 # via -r tests-min.in +numpy==1.24.4 + # via shapely packaging==24.1 # via # geoalchemy2 diff --git a/requirements/dev.txt b/requirements/dev.txt index 068c6c967..a4b4a85d0 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -167,6 +167,10 @@ nodeenv==1.9.1 # -r typing.txt # pre-commit # pyright +numpy==1.24.4 + # via + # -r typing.txt + # types-shapely packaging==24.1 # via # -r docs.txt diff --git a/requirements/typing.txt b/requirements/typing.txt index f166f92a9..49e0ec0de 100644 --- a/requirements/typing.txt +++ b/requirements/typing.txt @@ -65,6 +65,8 @@ mypy-extensions==1.0.0 # via mypy nodeenv==1.9.1 # via pyright +numpy==1.24.4 + # via types-shapely packaging==24.1 # via pytest platformdirs==4.2.2 From 733fb6e5c8ad1662d9e5bc1c178c93eaa9fe5e2b Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Fri, 15 Nov 2024 22:58:33 +0000 Subject: [PATCH 5/7] Add back new lines --- flask_admin/tests/test_base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flask_admin/tests/test_base.py b/flask_admin/tests/test_base.py index 47da01611..71a73a783 100644 --- a/flask_admin/tests/test_base.py +++ b/flask_admin/tests/test_base.py @@ -22,6 +22,7 @@ def app(): app.jinja_env.undefined = StrictUndefined yield app + class MockView(base.BaseView): # Various properties allow_call = True @@ -444,6 +445,7 @@ def test_add_links(app, admin): assert "TestMenuLink1" in data assert "TestMenuLink2" in data + def check_class_name(): view = MockView() assert view.name == "Mock View" From 84be32e237de739baa3060f74f5f97d20681f826 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Sat, 16 Nov 2024 00:12:56 +0000 Subject: [PATCH 6/7] Update other undefined situations --- .../templates/bootstrap4/admin/actions.html | 10 +++++-- .../templates/bootstrap4/admin/file/list.html | 4 +++ .../templates/bootstrap4/admin/lib.html | 28 +++++++++---------- .../bootstrap4/admin/model/list.html | 4 +-- .../bootstrap4/admin/model/row_actions.html | 4 +-- flask_admin/tests/conftest.py | 3 +- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/flask_admin/templates/bootstrap4/admin/actions.html b/flask_admin/templates/bootstrap4/admin/actions.html index 6884a095a..89899089b 100644 --- a/flask_admin/templates/bootstrap4/admin/actions.html +++ b/flask_admin/templates/bootstrap4/admin/actions.html @@ -14,12 +14,16 @@ {% macro form(actions, url) %} {% if actions %}
- {% if action_form.csrf_token %} + {% if action_form.csrf_token is defined and action_form.csrf_token %} {{ action_form.csrf_token }} - {% elif csrf_token %} + {% elif csrf_token is defined and csrf_token %} {% endif %} - {{ action_form.url(value=return_url) }} + {% if return_url is defined and return_url %} + {{ action_form.url(value=return_url) }} + {% else %} + {{ action_form.url() }} + {% endif %} {{ action_form.action() }}
{% endif %} diff --git a/flask_admin/templates/bootstrap4/admin/file/list.html b/flask_admin/templates/bootstrap4/admin/file/list.html index ca9ce77c0..dc9be0191 100644 --- a/flask_admin/templates/bootstrap4/admin/file/list.html +++ b/flask_admin/templates/bootstrap4/admin/file/list.html @@ -86,7 +86,9 @@ {% if name != '..' and admin_view.can_delete_dirs %}
{{ delete_form.path(value=path) }} + {% if delete_form.csrf_token is defined and delete_form.csrf_token %} {{ delete_form.csrf_token }} + {% endif %} @@ -95,7 +97,9 @@ {% else %} {{ delete_form.path(value=path) }} + {% if delete_form.csrf_token is defined and delete_form.csrf_token %} {{ delete_form.csrf_token }} + {% endif %} diff --git a/flask_admin/templates/bootstrap4/admin/lib.html b/flask_admin/templates/bootstrap4/admin/lib.html index 2358bbc28..382647c40 100644 --- a/flask_admin/templates/bootstrap4/admin/lib.html +++ b/flask_admin/templates/bootstrap4/admin/lib.html @@ -120,7 +120,7 @@ {% set prepend = kwargs.pop('prepend', None) %} {% set append = kwargs.pop('append', None) %}
-
{%- endif -%} {% endif %} - {% if field.widget.input_type == 'checkbox' %} + {% if field.widget.input_type is defined and field.widget.input_type == 'checkbox' %} {% set _class = kwargs.setdefault('class', '') %} - {% elif field.widget.input_type == 'file' %} + {% elif field.widget.input_type is defined and field.widget.input_type == 'file' %} {% set _class = kwargs.setdefault('class', 'form-control-file') %} {% else %} {% set _class = kwargs.setdefault('class', 'form-control') %} @@ -179,10 +179,10 @@

{{ text }}

{% if form.hidden_tag is defined %} {{ form.hidden_tag() }} {% else %} - {% if csrf_token %} + {% if csrf_token is defined and csrf_token %} {% endif %} - {% for f in form if f.widget.input_type == 'hidden' %} + {% for f in form if f.widget.input_type is defined and f.widget.input_type == 'hidden' %} {{ f }} {% endfor %} {% endif %} @@ -192,7 +192,7 @@

{{ text }}

{{ r(form, form_opts=form_opts) }} {% endfor %} {% else %} - {% for f in form if f.widget.input_type != 'hidden' %} + {% for f in form if f.widget.input_type is undefined or f.widget.input_type != 'hidden' %} {% if form_opts %} {% set kwargs = form_opts.widget_args.get(f.short_name, {}) %} {% else %} @@ -228,7 +228,7 @@

{{ text }}

{% if extra %} {{ extra }} {% endif %} - {% if cancel_url %} + {% if cancel_url is defined and cancel_url %} {{ _gettext('Cancel') }} {% endif %} @@ -247,31 +247,31 @@

{{ text }}

- {% if config.FLASK_ADMIN_MAPS %} + {% if config.FLASK_ADMIN_MAPS is defined and config.FLASK_ADMIN_MAPS %} {% endif %} - {% if editable_columns %} + {% if editable_columns is defined and editable_columns %} {% endif %} {% endmacro %} {% macro form_js() %} - {% if config.FLASK_ADMIN_MAPS %} + {% if config.FLASK_ADMIN_MAPS is defined and config.FLASK_ADMIN_MAPS %} - {% if config.FLASK_ADMIN_MAPS_SEARCH %} + {% if config.FLASK_ADMIN_MAPS_SEARCH is defined and config.FLASK_ADMIN_MAPS_SEARCH %} @@ -279,7 +279,7 @@

{{ text }}

{% endif %} {% endif %} - {% if editable_columns %} + {% if editable_columns is defined and editable_columns %} {% endif %} diff --git a/flask_admin/templates/bootstrap4/admin/model/list.html b/flask_admin/templates/bootstrap4/admin/model/list.html index 7609075bc..b7825ebe3 100644 --- a/flask_admin/templates/bootstrap4/admin/model/list.html +++ b/flask_admin/templates/bootstrap4/admin/model/list.html @@ -135,9 +135,9 @@ {% if admin_view.is_editable(c) %} {% set form = list_forms[get_pk_value(row)] %} - {% if form.csrf_token %} + {% if form.csrf_token is defined and form.csrf_token %} {{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=form.csrf_token._value()) }} - {% elif csrf_token %} + {% elif csrf_token is defined and csrf_token %} {{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=csrf_token()) }} {% else %} {{ form[c](pk=get_pk_value(row), display_value=get_value(row, c)) }} diff --git a/flask_admin/templates/bootstrap4/admin/model/row_actions.html b/flask_admin/templates/bootstrap4/admin/model/row_actions.html index 105b5fdf5..1fbfc5a56 100644 --- a/flask_admin/templates/bootstrap4/admin/model/row_actions.html +++ b/flask_admin/templates/bootstrap4/admin/model/row_actions.html @@ -26,9 +26,9 @@ {{ delete_form.id(value=get_pk_value(row)) }} {{ delete_form.url(value=return_url) }} - {% if delete_form.csrf_token %} + {% if delete_form.csrf_token is defined and delete_form.csrf_token %} {{ delete_form.csrf_token }} - {% elif csrf_token %} + {% elif csrf_token is defined and csrf_token %} {% endif %}