如何为Flask-Admin添加摘要行?

时间:2017-11-05 17:53:19

标签: python flask-admin

在我的flask-admin index_view中,我显示了我的行的财务信息。

我想在index_view表的底部添加一个额外的行" summary row",它汇总了所有列。

我怎样才能做到这一点?

enter image description here

1 个答案:

答案 0 :(得分:4)

您需要做几件事。提供自定义list.html模板并覆盖视图的$compile方法。在render方法中,将摘要数据注入kwargs,在自定义模板中使用摘要数据输出相应的html。您可以将摘要数据添加到现有数据表的末尾,或将其添加到单独的表中,如下例所示。

Flask-Admin Summary Table

这是一个使用Flask-Admin 1.5,SQLAlchemy和SQLite的自包含示例(两个文件)。 custom_list.html直接来自flask-admin list.html,我们正在操作从第68行开始的块:

render()

请注意,在render()方法中,摘要数据是一个dicts数组。每个词都有一个标题'属性(例如{% block model_list_table %} ... {% endblock %} 加上每个列的属性摘要数据是必需的。

<强> app.py

'title: 'Page Total'

<强>模板/管理/模型/ custom_list.html

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)