From c9ac167a303ce621b86d6835ce6c559df9ded074 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Fri, 23 Jul 2021 13:26:04 -0400 Subject: [PATCH 1/9] Re-located _arg_url_for macro to utils.html and renamed to public function arg_url_for --- .../templates/bootstrap/pagination.html | 17 ++++------------- flask_bootstrap/templates/bootstrap/utils.html | 10 ++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/flask_bootstrap/templates/bootstrap/pagination.html b/flask_bootstrap/templates/bootstrap/pagination.html index 5ef40eb9..f332f0b9 100644 --- a/flask_bootstrap/templates/bootstrap/pagination.html +++ b/flask_bootstrap/templates/bootstrap/pagination.html @@ -1,5 +1,6 @@ {# This file was part of Flask-Bootstrap and was modified under the terms of its BSD License. Copyright (c) 2013, Marc Brinkmann. All rights reserved. #} +{% from 'bootstrap/utils.html' import arg_url_for %} {% macro render_pager(pagination, fragment='', @@ -24,16 +25,6 @@ {%- endmacro %} -{% macro _arg_url_for(endpoint, base) %} - {# calls url_for() with a given endpoint and **base as the parameters, - additionally passing on all keyword_arguments (may overwrite existing ones) - #} - {%- with kargs = base.copy() -%} - {%- do kargs.update(kwargs) -%} - {{ url_for(endpoint, **kargs) }} - {%- endwith %} -{%- endmacro %} - {% macro render_pagination(pagination, endpoint=None, prev=('«')|safe, @@ -55,7 +46,7 @@ {# prev and next are only show if a symbol has been passed. #} {% if prev != None -%}
  • - {{ prev }} + {{ prev }}
  • {%- endif -%} @@ -63,7 +54,7 @@ {% if page %} {% if page != pagination.page %}
  • - {{ page }} + {{ page }}
  • {% else %}
  • @@ -77,7 +68,7 @@ {% if next != None -%}
  • - {{ next }} + {{ next }}
  • {%- endif -%} diff --git a/flask_bootstrap/templates/bootstrap/utils.html b/flask_bootstrap/templates/bootstrap/utils.html index 81d76f80..1ff10f1a 100644 --- a/flask_bootstrap/templates/bootstrap/utils.html +++ b/flask_bootstrap/templates/bootstrap/utils.html @@ -61,3 +61,13 @@ {% endmacro %} + +{% macro arg_url_for(endpoint, base) %} + {# calls url_for() with a given endpoint and **base as the parameters, + additionally passing on all keyword_arguments (may overwrite existing ones) + #} + {%- with kargs = base.copy() -%} + {%- do kargs.update(kwargs) -%} + {{ url_for(endpoint, **kargs) }} + {%- endwith %} +{%- endmacro %} From 67080feabd698682aed93286701e7f47b377eb81 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Fri, 23 Jul 2021 13:30:26 -0400 Subject: [PATCH 2/9] Fixed url-rendering with url_for by adding the ability to pass in a model to render_table. Added ability to supply url parameters to render_table by allowing passage of a list (first item is the route namespace, second item is a list of tuples mapping variables to placeholders representing fields present in the model) --- .../templates/bootstrap/table.html | 83 ++++++++++++++----- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/flask_bootstrap/templates/bootstrap/table.html b/flask_bootstrap/templates/bootstrap/table.html index a21deaee..e5473360 100644 --- a/flask_bootstrap/templates/bootstrap/table.html +++ b/flask_bootstrap/templates/bootstrap/table.html @@ -1,10 +1,30 @@ -{% from 'bootstrap/utils.html' import render_icon %} +{% from 'bootstrap/utils.html' import render_icon, arg_url_for %} {% macro deprecate_old_pk_placeholder() %} {{ warn('The default action primary key placeholder has changed to ":id", please update. The support to the old value (":primary_key") will be removed in version 2.0.') }} {% endmacro %} +{% macro build_url(endpoint, model, pk, kwargs) %} + {% with url_params = {} -%} + {%- do url_params.update(request.view_args if not endpoint else {}), + url_params.update(request.args if not endpoint else {}) -%} + {% with record = model.query.get(pk) %} + {% for kwarg, value in kwargs %} + {% if value.startswith(':') and '.' in value %} + {%- set value = value[1:].split('.') -%} + {%- do url_params.update({kwarg: record[value[0]][value[1]]}) -%} + {% elif value.startswith(':') %} + {%- set value = value[1:] -%} + {%- do url_params.update({kwarg: record[value]}) -%} + {% else %} + {%- do url_params.update({kwarg: value}) -%} + {% endif %} + {% endfor %} + {% endwith -%} + {{ arg_url_for(endpoint, url_params) }} + {%- endwith %} +{%- endmacro %} {% macro render_table(data, titles=None, @@ -15,6 +35,7 @@ header_classes=None, responsive=False, responsive_class='table-responsive', + model=None, show_actions=False, actions_title='Actions', custom_actions=None, @@ -40,9 +61,11 @@ {% endfor %} {% if show_actions %} {{ actions_title }} - {% if new_url %} + {% if new_url %} + {{ render_icon('plus-circle-fill') }} - {% endif %} + + {% endif %} {% endif %} @@ -61,43 +84,61 @@ {% if custom_actions %} {% for (action_name, action_icon, action_url) in custom_actions %} - {% if ':primary_key' in action_url %} + {% if ':primary_key' in action_url|join('') %} {% set action_pk_placeholder = ':primary_key' %} {% set w = deprecate_old_pk_placeholder() %} {% endif %} {{ render_icon(action_icon) }} {% endfor %} {% endif %} {% if view_url %} - {% if ':primary_key' in view_url %} + {% if ':primary_key' in view_url|join('') %} {% set action_pk_placeholder = ':primary_key' %} {% set w = deprecate_old_pk_placeholder() %} {% endif %} - - {{ render_icon('eye-fill') }} - + + {{ render_icon('eye-fill') }} + {% endif %} - {% if edit_url %} - {% if ':primary_key' in edit_url %} + {% if edit_url -%} + {% if ':primary_key' in edit_url|join('') %} {% set action_pk_placeholder = ':primary_key' %} {% set w = deprecate_old_pk_placeholder() %} {% endif %} - - {{ render_icon('pencil-fill') }} - - {% endif %} + + {{ render_icon('pencil-fill') }} + + {%- endif %} {% if delete_url %} - {% if ':primary_key' in delete_url %} + {% if ':primary_key' in delete_url|join('') %} {% set action_pk_placeholder = ':primary_key' %} {% set w = deprecate_old_pk_placeholder() %} {% endif %} -
    + Date: Fri, 23 Jul 2021 13:32:20 -0400 Subject: [PATCH 3/9] Added tests for fixed url-processors (string and int) and for dynamic placeholders representing fields of a model. --- tests/test_render_table.py | 48 ++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/tests/test_render_table.py b/tests/test_render_table.py index f6a1bb8a..d7370330 100644 --- a/tests/test_render_table.py +++ b/tests/test_render_table.py @@ -147,15 +147,17 @@ def test_render_table_with_actions(self, app, client): class Message(db.Model): id = db.Column(db.Integer, primary_key=True) + sender = db.Column(db.String(20)) + recipient = db.Column(db.String(20)) text = db.Column(db.Text) - @app.route('/table//resend') - def test_resend_message(message_id): - return 'Re-sending {}'.format(message_id) + @app.route('/table///resend') + def test_resend_message(recipient, message_id): + return 'Re-sending {} to {}'.format(message_id, recipient) - @app.route('/table//view') - def test_view_message(message_id): - return 'Viewing {}'.format(message_id) + @app.route('/table///view') + def test_view_message(sender, message_id): + return 'Viewing {} from {}'.format(message_id, sender) @app.route('/table/new-message') def test_create_message(): @@ -166,7 +168,11 @@ def test(): db.drop_all() db.create_all() for i in range(10): - m = Message(text='Test message {}'.format(i+1)) + m = Message( + text='Test message {}'.format(i+1), + sender='me', + recipient='john_doe' + ) db.session.add(m) db.session.commit() page = request.args.get('page', 1, type=int) @@ -175,20 +181,25 @@ def test(): titles = [('id', '#'), ('text', 'Message')] return render_template_string(''' {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, titles, show_actions=True, + {{ render_table(messages, titles, model=model, show_actions=True, custom_actions=[ - ('Resend', 'bootstrap-reboot', url_for('test_resend_message', message_id=':id')) + ( + 'Resend', + 'bootstrap-reboot', + ('test_resend_message', [('recipient', ':recipient'), ('message_id', ':id')]) + ) ], - view_url=url_for('test_view_message', message_id=':id'), + view_url=('test_view_message', [('sender', ':sender'), ('message_id', ':id')]), new_url=url_for('test_create_message')) }} - ''', titles=titles, messages=messages) + ''', titles=titles, model=Message, messages=messages) response = client.get('/table') data = response.get_data(as_text=True) + print(data) assert 'icons/bootstrap-icons.svg#bootstrap-reboot' in data - assert 'href="/table/1/resend"' in data + assert 'href="/table/john_doe/1/resend"' in data assert 'title="Resend">' in data - assert 'href="/table/1/view"' in data + assert 'href="/table/me/1/view"' in data assert 'href="/table/new-message"' in data def test_customize_icon_title_of_table_actions(self, app, client): @@ -217,10 +228,13 @@ def test(): pagination = Message.query.paginate(page, per_page=10) messages = pagination.items return render_template_string(''' - {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, show_actions=True, view_url='/view', edit_url='/edit', - delete_url='/delete', new_url='/new') }} - ''', messages=messages) + {% from 'bootstrap/table.html' import render_table %} + {{ render_table(messages, model=model, show_actions=True, + view_url='/view', + edit_url='/edit', + delete_url='/delete', + new_url='/new') }} + ''', model=Message, messages=messages) response = client.get('/table') data = response.get_data(as_text=True) From 072aef73fafc2b2442eb1194d704553ea4da7fea Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Fri, 23 Jul 2021 13:44:29 -0400 Subject: [PATCH 4/9] Corrected flake8 errors --- tests/test_render_table.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/test_render_table.py b/tests/test_render_table.py index d7370330..2606f5c2 100644 --- a/tests/test_render_table.py +++ b/tests/test_render_table.py @@ -184,7 +184,7 @@ def test(): {{ render_table(messages, titles, model=model, show_actions=True, custom_actions=[ ( - 'Resend', + 'Resend', 'bootstrap-reboot', ('test_resend_message', [('recipient', ':recipient'), ('message_id', ':id')]) ) @@ -195,7 +195,6 @@ def test(): response = client.get('/table') data = response.get_data(as_text=True) - print(data) assert 'icons/bootstrap-icons.svg#bootstrap-reboot' in data assert 'href="/table/john_doe/1/resend"' in data assert 'title="Resend">' in data @@ -229,10 +228,10 @@ def test(): messages = pagination.items return render_template_string(''' {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, model=model, show_actions=True, - view_url='/view', - edit_url='/edit', - delete_url='/delete', + {{ render_table(messages, model=model, show_actions=True, + view_url='/view', + edit_url='/edit', + delete_url='/delete', new_url='/new') }} ''', model=Message, messages=messages) From f2862206fe404cb9f9c2193116c8f8c7d6ac4be5 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Mon, 30 Aug 2021 09:04:05 -0400 Subject: [PATCH 5/9] Changed model parameter to query, so a subset query can be used. Also, updated tests to reflect change. --- flask_bootstrap/templates/bootstrap/table.html | 14 +++++++------- tests/test_render_table.py | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/flask_bootstrap/templates/bootstrap/table.html b/flask_bootstrap/templates/bootstrap/table.html index e5473360..24be3aa1 100644 --- a/flask_bootstrap/templates/bootstrap/table.html +++ b/flask_bootstrap/templates/bootstrap/table.html @@ -5,11 +5,11 @@ The support to the old value (":primary_key") will be removed in version 2.0.') }} {% endmacro %} -{% macro build_url(endpoint, model, pk, kwargs) %} +{% macro build_url(endpoint, query, pk, kwargs) %} {% with url_params = {} -%} {%- do url_params.update(request.view_args if not endpoint else {}), url_params.update(request.args if not endpoint else {}) -%} - {% with record = model.query.get(pk) %} + {% with record = query.get(pk) %} {% for kwarg, value in kwargs %} {% if value.startswith(':') and '.' in value %} {%- set value = value[1:].split('.') -%} @@ -35,7 +35,7 @@ header_classes=None, responsive=False, responsive_class='table-responsive', - model=None, + query=None, show_actions=False, actions_title='Actions', custom_actions=None, @@ -92,7 +92,7 @@ {% if action_url is string %} href="{{ action_url }}" {% else %} - href="{{ build_url(action_url[0], model, row[primary_key], action_url[1])|trim }}" + href="{{ build_url(action_url[0], query, row[primary_key], action_url[1])|trim }}" {% endif %} title="{{ action_name }}">{{ render_icon(action_icon) }} {% endfor %} @@ -106,7 +106,7 @@ {% if view_url is string %} href="{{ view_url }}" {% else %} - href="{{ build_url(view_url[0], model, row[primary_key], view_url[1])|trim }}" + href="{{ build_url(view_url[0], query, row[primary_key], view_url[1])|trim }}" {% endif %} title="{{ config['BOOTSTRAP_TABLE_VIEW_TITLE'] }}"> {{ render_icon('eye-fill') }} @@ -121,7 +121,7 @@ {% if edit_url is string %} href="{{ edit_url }}" {% else %} - href="{{ build_url(edit_url[0], model, row[primary_key], edit_url[1])|trim }}" + href="{{ build_url(edit_url[0], query, row[primary_key], edit_url[1])|trim }}" {% endif %} title="{{ config['BOOTSTRAP_TABLE_EDIT_TITLE'] }}"> {{ render_icon('pencil-fill') }} @@ -136,7 +136,7 @@ {% if delete_url is string %} action="{{ delete_url }}" {% else %} - action="{{ build_url(delete_url[0], model, row[primary_key], delete_url[1])|trim }}" + action="{{ build_url(delete_url[0], query, row[primary_key], delete_url[1])|trim }}" {% endif %} method="post"> diff --git a/tests/test_render_table.py b/tests/test_render_table.py index 2606f5c2..964d5334 100644 --- a/tests/test_render_table.py +++ b/tests/test_render_table.py @@ -181,7 +181,7 @@ def test(): titles = [('id', '#'), ('text', 'Message')] return render_template_string(''' {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, titles, model=model, show_actions=True, + {{ render_table(messages, titles, query=query, show_actions=True, custom_actions=[ ( 'Resend', @@ -191,7 +191,7 @@ def test(): ], view_url=('test_view_message', [('sender', ':sender'), ('message_id', ':id')]), new_url=url_for('test_create_message')) }} - ''', titles=titles, model=Message, messages=messages) + ''', titles=titles, query=Message.query, messages=messages) response = client.get('/table') data = response.get_data(as_text=True) @@ -228,12 +228,12 @@ def test(): messages = pagination.items return render_template_string(''' {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, model=model, show_actions=True, + {{ render_table(messages, query=query, show_actions=True, view_url='/view', edit_url='/edit', delete_url='/delete', new_url='/new') }} - ''', model=Message, messages=messages) + ''', query=Message.query, messages=messages) response = client.get('/table') data = response.get_data(as_text=True) From 467fd9ed3b8526a460da7634b2a985138cc75596 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Mon, 30 Aug 2021 09:10:34 -0400 Subject: [PATCH 6/9] Updated documentation and changelog --- CHANGES.rst | 1 + docs/macros.rst | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 1f35491e..cb63d593 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,6 +19,7 @@ Release date: - - Add configuration ``BOOTSTRAP_TABLE_VIEW_TITLE``, ``BOOTSTRAP_TABLE_EDIT_TITLE``, ``BOOTSTRAP_TABLE_DELETE_TITLE``, ``BOOTSTRAP_TABLE_NEW_TITLE`` to support changing the icon title of table actions. +- Fix bug preventing usage of Flask's default path converters (`#146 `__). 1.7.0 diff --git a/docs/macros.rst b/docs/macros.rst index 1048e28b..b35fe176 100644 --- a/docs/macros.rst +++ b/docs/macros.rst @@ -431,6 +431,7 @@ API header_classes=None,\ responsive=False,\ responsive_class='table-responsive',\ + query=None,\ show_actions=False,\ actions_title='Actions',\ custom_actions=None,\ @@ -450,6 +451,8 @@ API :param header_classes: A string of classes to apply to the table header (e.g ``'thead-dark'``). :param responsive: Whether to enable/disable table responsiveness. :param responsive_class: The responsive class to apply to the table. Default is ``'table-responsive'``. + :param query: The query originating from the target Model. This allows for proper usage of Flask's default + path converter types (ie. ``str``, ``int``). :param show_actions: Whether to display the actions column. Default is ``False``. :param actions_title: Title for the actions column header. Default is ``'Actions'``. :param custom_actions: A list of tuples for creating custom action buttons, where each tuple contains From d7c7c05b54bfa5de881e540ebf08f6531a648a21 Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Tue, 31 Aug 2021 10:06:09 -0400 Subject: [PATCH 7/9] Implemented requested changes/additions --- CHANGES.rst | 3 ++- docs/macros.rst | 19 ++++++++++++------- .../templates/bootstrap/table.html | 6 +++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 8753b47f..9aafd59f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,7 +19,8 @@ Release date: - - Add configuration ``BOOTSTRAP_TABLE_VIEW_TITLE``, ``BOOTSTRAP_TABLE_EDIT_TITLE``, ``BOOTSTRAP_TABLE_DELETE_TITLE``, ``BOOTSTRAP_TABLE_NEW_TITLE`` to support changing the icon title of table actions. -- Fix bug preventing usage of Flask's default path converters (`#146 `__). +- Introduce a new and better way to pass table action URLs to support the usage of ``Flask``'s path converters + (`#146 `__). 1.7.0 diff --git a/docs/macros.rst b/docs/macros.rst index fca6a94c..b9439366 100644 --- a/docs/macros.rst +++ b/docs/macros.rst @@ -451,17 +451,22 @@ API :param header_classes: A string of classes to apply to the table header (e.g ``'thead-dark'``). :param responsive: Whether to enable/disable table responsiveness. :param responsive_class: The responsive class to apply to the table. Default is ``'table-responsive'``. - :param query: The query originating from the target Model. This allows for proper usage of Flask's default - path converter types (ie. ``str``, ``int``). + :param query: The query originating from the target Model. Used to build custom_action, view, edit, delete, and + new urls. This allows for proper usage of Flask's default path converter types (i.e. ``str``, ``int``) + (e.g. ``Model.query``, ``Model.query.filter_by(active=True)``). When using this tuples are accepted in + place of view, edit, delete, new, and custom_actions urls. Defaults to ``None`` to allow for + backwards-compatibility. Tuple format: + ``('route_name', [('db_model_fieldname', ':url_parameter_name')])``. ``db_model_fieldname`` may also + contain dots to access relationships and their fields (e.g. ``db_model_relationship_field.name``). :param show_actions: Whether to display the actions column. Default is ``False``. :param actions_title: Title for the actions column header. Default is ``'Actions'``. :param custom_actions: A list of tuples for creating custom action buttons, where each tuple contains ('Title Text displayed on hover', 'bootstrap icon name', 'url_for()') - (e.g. ``[('Run', 'play-fill', url_for('run_report', report_id=':id'))]``). - :param view_url: URL to use for the view action. - :param edit_url: URL to use for the edit action. - :param delete_url: URL to use for the delete action. - :param new_url: URL to use for the create action (new in version 1.6.0). + (e.g. ``[('Run', 'play-fill', ('run_report', [('report_id', ':id')]))]``). + :param view_url: URL or tuple (see :param:`query`) to use for the view action. + :param edit_url: URL or tuple (see :param:`query`) to use for the edit action. + :param delete_url: URL or tuple (see :param:`query`) to use for the delete action. + :param new_url: URL or tuple (see :param:`query`) to use for the create action (new in version 1.6.0). :param action_pk_placeholder: The placeholder which replaced by the primary key when build the action URLs. Default is ``':id'``. .. tip:: The default value of ``action_pk_placeholder`` changed to ``:id`` in version 1.7.0. diff --git a/flask_bootstrap/templates/bootstrap/table.html b/flask_bootstrap/templates/bootstrap/table.html index 24be3aa1..17d38087 100644 --- a/flask_bootstrap/templates/bootstrap/table.html +++ b/flask_bootstrap/templates/bootstrap/table.html @@ -84,15 +84,15 @@ {% if custom_actions %} {% for (action_name, action_icon, action_url) in custom_actions %} - {% if ':primary_key' in action_url|join('') %} + {% if ':primary_key' in action_url | join('') %} {% set action_pk_placeholder = ':primary_key' %} {% set w = deprecate_old_pk_placeholder() %} {% endif %} {{ render_icon(action_icon) }} {% endfor %} From 9483b939a8a3b0c9268b3293fc767a5f7cfd735e Mon Sep 17 00:00:00 2001 From: Mike Hill Date: Wed, 1 Sep 2021 12:34:00 -0400 Subject: [PATCH 8/9] Reverted new parameter back to model --- docs/macros.rst | 17 ++++++++--------- flask_bootstrap/templates/bootstrap/table.html | 14 +++++++------- tests/test_render_table.py | 8 ++++---- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/docs/macros.rst b/docs/macros.rst index b9439366..7aa2e237 100644 --- a/docs/macros.rst +++ b/docs/macros.rst @@ -451,11 +451,10 @@ API :param header_classes: A string of classes to apply to the table header (e.g ``'thead-dark'``). :param responsive: Whether to enable/disable table responsiveness. :param responsive_class: The responsive class to apply to the table. Default is ``'table-responsive'``. - :param query: The query originating from the target Model. Used to build custom_action, view, edit, delete, and - new urls. This allows for proper usage of Flask's default path converter types (i.e. ``str``, ``int``) - (e.g. ``Model.query``, ``Model.query.filter_by(active=True)``). When using this tuples are accepted in - place of view, edit, delete, new, and custom_actions urls. Defaults to ``None`` to allow for - backwards-compatibility. Tuple format: + :param model: The model used to build custom_action, view, edit, delete, and new urls. This allows for proper + usage of Flask's default path converter types (i.e. ``str``, ``int``) (e.g. ``Model``). When using + this tuples are accepted in place of view, edit, delete, new, and custom_actions urls. Defaults to + ``None`` to allow for backwards-compatibility. Tuple format: ``('route_name', [('db_model_fieldname', ':url_parameter_name')])``. ``db_model_fieldname`` may also contain dots to access relationships and their fields (e.g. ``db_model_relationship_field.name``). :param show_actions: Whether to display the actions column. Default is ``False``. @@ -463,10 +462,10 @@ API :param custom_actions: A list of tuples for creating custom action buttons, where each tuple contains ('Title Text displayed on hover', 'bootstrap icon name', 'url_for()') (e.g. ``[('Run', 'play-fill', ('run_report', [('report_id', ':id')]))]``). - :param view_url: URL or tuple (see :param:`query`) to use for the view action. - :param edit_url: URL or tuple (see :param:`query`) to use for the edit action. - :param delete_url: URL or tuple (see :param:`query`) to use for the delete action. - :param new_url: URL or tuple (see :param:`query`) to use for the create action (new in version 1.6.0). + :param view_url: URL or tuple (see :param:`model`) to use for the view action. + :param edit_url: URL or tuple (see :param:`model`) to use for the edit action. + :param delete_url: URL or tuple (see :param:`model`) to use for the delete action. + :param new_url: URL or tuple (see :param:`model`) to use for the create action (new in version 1.6.0). :param action_pk_placeholder: The placeholder which replaced by the primary key when build the action URLs. Default is ``':id'``. .. tip:: The default value of ``action_pk_placeholder`` changed to ``:id`` in version 1.7.0. diff --git a/flask_bootstrap/templates/bootstrap/table.html b/flask_bootstrap/templates/bootstrap/table.html index 17d38087..2a3d1932 100644 --- a/flask_bootstrap/templates/bootstrap/table.html +++ b/flask_bootstrap/templates/bootstrap/table.html @@ -5,11 +5,11 @@ The support to the old value (":primary_key") will be removed in version 2.0.') }} {% endmacro %} -{% macro build_url(endpoint, query, pk, kwargs) %} +{% macro build_url(endpoint, model, pk, kwargs) %} {% with url_params = {} -%} {%- do url_params.update(request.view_args if not endpoint else {}), url_params.update(request.args if not endpoint else {}) -%} - {% with record = query.get(pk) %} + {% with record = model.query.get(pk) %} {% for kwarg, value in kwargs %} {% if value.startswith(':') and '.' in value %} {%- set value = value[1:].split('.') -%} @@ -35,7 +35,7 @@ header_classes=None, responsive=False, responsive_class='table-responsive', - query=None, + model=None, show_actions=False, actions_title='Actions', custom_actions=None, @@ -92,7 +92,7 @@ {% if action_url is string %} href="{{ action_url | replace(action_pk_placeholder, row[primary_key]) }}" {% else %} - href="{{ build_url(action_url[0], query, row[primary_key], action_url[1]) | trim }}" + href="{{ build_url(action_url[0], model, row[primary_key], action_url[1]) | trim }}" {% endif %} title="{{ action_name }}">{{ render_icon(action_icon) }} {% endfor %} @@ -106,7 +106,7 @@ {% if view_url is string %} href="{{ view_url }}" {% else %} - href="{{ build_url(view_url[0], query, row[primary_key], view_url[1])|trim }}" + href="{{ build_url(view_url[0], model, row[primary_key], view_url[1])|trim }}" {% endif %} title="{{ config['BOOTSTRAP_TABLE_VIEW_TITLE'] }}"> {{ render_icon('eye-fill') }} @@ -121,7 +121,7 @@ {% if edit_url is string %} href="{{ edit_url }}" {% else %} - href="{{ build_url(edit_url[0], query, row[primary_key], edit_url[1])|trim }}" + href="{{ build_url(edit_url[0], model, row[primary_key], edit_url[1])|trim }}" {% endif %} title="{{ config['BOOTSTRAP_TABLE_EDIT_TITLE'] }}"> {{ render_icon('pencil-fill') }} @@ -136,7 +136,7 @@ {% if delete_url is string %} action="{{ delete_url }}" {% else %} - action="{{ build_url(delete_url[0], query, row[primary_key], delete_url[1])|trim }}" + action="{{ build_url(delete_url[0], model, row[primary_key], delete_url[1])|trim }}" {% endif %} method="post"> diff --git a/tests/test_render_table.py b/tests/test_render_table.py index 964d5334..2606f5c2 100644 --- a/tests/test_render_table.py +++ b/tests/test_render_table.py @@ -181,7 +181,7 @@ def test(): titles = [('id', '#'), ('text', 'Message')] return render_template_string(''' {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, titles, query=query, show_actions=True, + {{ render_table(messages, titles, model=model, show_actions=True, custom_actions=[ ( 'Resend', @@ -191,7 +191,7 @@ def test(): ], view_url=('test_view_message', [('sender', ':sender'), ('message_id', ':id')]), new_url=url_for('test_create_message')) }} - ''', titles=titles, query=Message.query, messages=messages) + ''', titles=titles, model=Message, messages=messages) response = client.get('/table') data = response.get_data(as_text=True) @@ -228,12 +228,12 @@ def test(): messages = pagination.items return render_template_string(''' {% from 'bootstrap/table.html' import render_table %} - {{ render_table(messages, query=query, show_actions=True, + {{ render_table(messages, model=model, show_actions=True, view_url='/view', edit_url='/edit', delete_url='/delete', new_url='/new') }} - ''', query=Message.query, messages=messages) + ''', model=Message, messages=messages) response = client.get('/table') data = response.get_data(as_text=True) From e909d732a06cae12f7bf4292e42c6dfc236d9269 Mon Sep 17 00:00:00 2001 From: Grey Li Date: Thu, 2 Sep 2021 11:16:35 +0800 Subject: [PATCH 9/9] Update arg name in docs --- docs/macros.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/macros.rst b/docs/macros.rst index 7aa2e237..486f5944 100644 --- a/docs/macros.rst +++ b/docs/macros.rst @@ -431,7 +431,7 @@ API header_classes=None,\ responsive=False,\ responsive_class='table-responsive',\ - query=None,\ + model=None,\ show_actions=False,\ actions_title='Actions',\ custom_actions=None,\