stackoverflow.com/questions/46914054/...

м флеш-администраторе index_view я отображаю финансовую информацию для своих строк.

Я хотел бы добавить дополнительную строку, "итоговую строку", внизу моей таблицы index_view, которая суммирует все столбцы.

Как я могу сделать это?

Ответы на вопрос(1)

Решение Вопроса

которые вам нужно сделать. Предоставьте собственный шаблон list.html и переопределитеrender() метод для представления. В методе рендеринга введите ваши сводные данные в kwargs, а в пользовательском шаблоне используйте сводные данные для вывода соответствующего HTML. Вы можете добавить сводные данные в конец существующей таблицы данных или добавить их в отдельную таблицу, как показано в примере ниже.

Вот отдельный пример (два файла) с использованием Flask-Admin 1.5, SQLAlchemy и SQLite. custom_list.html берется непосредственно из flask-adminlist.html и мы манипулируем блоком, начинающимся со строки 68:

{% block model_list_table %}
    ...
{% endblock %}

Обратите внимание, что в методе render () сводные данные представляют собой массив dicts. У каждого диктанта есть атрибут title (например,'title: 'Page Total' плюс для каждого столбца требуется атрибут сводных данных.

app.py

import random
import string

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib.sqla import ModelView
from flask_admin import Admin, expose

# Create application
from sqlalchemy import func

app = Flask(__name__)

# Create dummy secrey key so we can use sessions
app.config['SECRET_KEY'] = '123456790'

# Create in-memory database
app.config['DATABASE_FILE'] = 'sample_db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
db = SQLAlchemy(app)


# Flask views
@app.route('/')
def index():
    return '<a href="/admin/">Click me to get to Admin!</a>'


class Project(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False, unique=True)
    cost = db.Column(db.Integer(), nullable=False)

    def __str__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return "Name: {name}; Cost : {cost}".format(name=self.name, cost=self.cost)


class ProjectView(ModelView):
    # don't call the custom page list.html as you'll get a recursive call
    list_template = 'admin/model/custom_list.html'
    form_columns = ('name', 'cost')
    page_size = 5

    def page_cost(self, current_page):
        # this should take into account any filters/search inplace
        _query = self.session.query(Project).limit(self.page_size).offset(current_page * self.page_size)
        return sum([p.cost for p in _query])

    def total_cost(self):
        # this should take into account any filters/search inplace
        return self.session.query(func.sum(Project.cost)).scalar()

    def render(self, template, **kwargs):
        # we are only interested in the list page
        if template == 'admin/model/custom_list.html':
            # append a summary_data dictionary into kwargs
            _current_page = kwargs['page']
            kwargs['summary_data'] = [
                {'title': 'Page Total', 'name': None, 'cost': self.page_cost(_current_page)},
                {'title': 'Grand Total', 'name': None, 'cost': self.total_cost()},
            ]
        return super(ProjectView, self).render(template, **kwargs)


admin = Admin(app, template_mode="bootstrap3")
admin.add_view(ProjectView(Project, db.session))


def build_sample_db():
    db.drop_all()
    db.create_all()

    for _ in range(0, 100):
        _cost = random.randrange(1, 1000)
        _project = Project(
            name=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)),
            cost=_cost
        )
        db.session.add(_project)

    db.session.commit()


if __name__ == '__main__':
    build_sample_db()
    app.run(port=5000, debug=True)

шаблоны / администратор / модель / custom_list.html

{% extends 'admin/model/list.html' %}

{% block model_list_table %}
<div class="table-responsive">
<table class="table table-striped table-bordered table-hover model-list">
    <thead>
        <tr>
            {% block list_header scoped %}
                {% if actions %}
                <th class="list-checkbox-column">
                    <input type="checkbox" name="rowtoggle" class="action-rowtoggle" title="{{ _gettext('Select all records') }}" />
                </th>
                {% endif %}
                {% block list_row_actions_header %}
                    {% if admin_view.column_display_actions %}
                    <th class="col-md-1">&nbsp;</th>
                    {% endif %}
                {% endblock %}
                {% for c, name in list_columns %}
                {% set column = loop.index0 %}
                <th class="column-header col-{{c}}">
                    {% if admin_view.is_sortable(c) %}
                        {% if sort_column == column %}
                            <a href="{{ sort_url(column, True) }}" title="{{ _gettext('Sort by %(name)s', name=name) }}">
                                {{ name }}
                                {% if sort_desc %}
                                    <span class="fa fa-chevron-up glyphicon glyphicon-chevron-up"></span>
                                {% else %}
                                    <span class="fa fa-chevron-down glyphicon glyphicon-chevron-down"></span>
                                {% endif %}
                            </a>
                        {% else %}
                            <a href="{{ sort_url(column) }}" title="{{ _gettext('Sort by %(name)s', name=name) }}">{{ name }}</a>
                        {% endif %}
                    {% else %}
                        {{ name }}
                    {% endif %}
                    {% if admin_view.column_descriptions.get(c) %}
                        <a class="fa fa-question-circle glyphicon glyphicon-question-sign"
                           title="{{ admin_view.column_descriptions[c] }}"
                           href="javascript:void(0)" data-role="tooltip"
                        ></a>
                    {% endif %}
                </th>
                {% endfor %}
            {% endblock %}
        </tr>
    </thead>
    {% for row in data %}
    <tr>
        {% block list_row scoped %}
            {% if actions %}
            <td>
                <input type="checkbox" name="rowid" class="action-checkbox" value="{{ get_pk_value(row) }}" title="{{ _gettext('Select record') }}" />
            </td>
            {% endif %}
            {% block list_row_actions_column scoped %}
                {% if admin_view.column_display_actions %}
                <td class="list-buttons-column">
                    {% block list_row_actions scoped %}
                      {% for action in list_row_actions %}
                      {{ action.render_ctx(get_pk_value(row), row) }}
                      {% endfor %}
                    {% endblock %}
                </td>
                {%- endif -%}
            {% endblock %}

            {% for c, name in list_columns %}
                <td class="col-{{c}}">
                {% if admin_view.is_editable(c) %}
                    {% set form = list_forms[get_pk_value(row)] %}
                    {% if form.csrf_token %}
                    {{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=form.csrf_token._value()) }}
                    {% else %}
                    {{ form[c](pk=get_pk_value(row), display_value=get_value(row, c)) }}
                    {% endif %}
                {% else %}
                {{ get_value(row, c) }}
                {% endif %}
                </td>
            {% endfor %}
        {% endblock %}
    </tr>
    {% else %}
    <tr>
        <td colspan="999">
            {% block empty_list_message %}
            <div class="text-center">
                {{ admin_view.get_empty_list_message() }}
            </div>
            {% endblock %}
        </td>
    </tr>
    {% endfor %}
</table>
</div>

<h3>Summaries</h3>

<div class="table-responsive">
    <table class="table table-striped table-bordered table-hover model-list">
        <thead>
            <tr>
                {% if actions %}
                <th class="list-checkbox-column">
                </th>
                {% endif %}

                <th class="col-md-1"></th>
                {% for c, name in list_columns %}
                    {% set column = loop.index0 %}
                    <th class="column-header col-{{c}}">
                        {{ name }}
                    </th>
                {% endfor %}
            </tr>
        </thead>
        {% for row in summary_data %}
            <tr>
                <td colspan="2"><strong>{{ row['title'] or ''}}</strong></td>
                {% for c, name in list_columns %}
                    <td class="col-{{c}}">
                        {{ row[c] or ''}}
                    </td>
                {% endfor %}
            </tr>
        {% endfor %}
    </table>
</div>


{% block list_pager %}
{% if num_pages is not none %}
{{ lib.pager(page, num_pages, pager_url) }}
{% else %}
{{ lib.simple_pager(page, data|length == page_size, pager_url) }}
{% endif %}
{% endblock %}
{% endblock %}
 Sparrowcide09 нояб. 2017 г., 12:10
Я знаю, что это не имеет отношения к вопросу, но я хотел бы, чтобы ваше мнение касалось несвязанного вопроса о реализации контроля доступа для Flask-Admin. Вам будет интересно посмотреть?stackoverflow.com/questions/46914054/...
 Sparrowcide09 нояб. 2017 г., 12:08
Спасибо за подробный ответ! Это здорово!

Ваш ответ на вопрос