Zé Miguel
Zé Miguel

Reputation: 41

Flask Admin Models - Summary row

I'm using Flask Admin (https://github.com/jonalxh/Flask-Admin-Dashboard) and I have a doubt.

Let's say that I have a Model with:

Product

Serial Number

Price

I was looking for a way to display a new row that would display the total price of products in stock.

Can someone point me to the right direction?

Thank you.

I have already looked into this but when I display a custom view,I can't do CRUD actions like I do on the "standard" models view: How do you add a summary row for Flask-Admin?

P.S: I'm learning python so please excuse me if this is a basic issue that I'm wasting your time with

Upvotes: 3

Views: 1880

Answers (1)

pjcunningham
pjcunningham

Reputation: 8046

The method outlined in the answer to the referenced question can also be made to work with Flask-Admin-Dashboard.

I have created a sample project Flask-Admin-Dashboard-Summary on Github.

Summary Rows for Project View

Below are the essential concepts.

To show a summary table a view needs to:

  • inject summary values into the view
  • define what Jinja template to use and suitably modify it to use the injected summary values

Setting up the Jinja template

templates/admin/model/summary_list.html is a direct copy of list.html, from the Flask-Admin Bootstrap 3 template folder.

Note the file name, summary_list.html, as this is used in the view definition's render method.

The following block of html has been inserted at line 163:

{# This adds the summary data #}
{% for row in summary_data %}
<tr>
    {% if actions %}
    <td>
        {# leave this empty #}
    </td>
    {% endif %}
    {# This is the summary line title and goes in the action column, note that the action may not be visible!!! #}
    {% if admin_view.column_display_actions %}
        <td><strong>{{ row['title'] or ''}}</strong></td>
    {% endif %}
    {# This is the summary line data and goes in the individual columns #}
    {% for c, name in list_columns %}
        <td class="col-{{c}}">
            <strong>{{ row[c] or ''}}</strong>
        </td>
    {% endfor %}
</tr>
{% endfor %}

Setting up the view

Line 61, define the template to use:

# don't call the custom page list.html as you'll get a recursive call
list_template = 'admin/model/summary_list.html'

Line 75, override the view's render(self, template, **kwargs) method:

def render(self, template, **kwargs):
    # we are only interested in the summary_list page
    if template == 'admin/model/summary_list.html':
        # append a summary_data dictionary into kwargs
        # The title attribute value appears in the actions column
        # all other attributes correspond to their respective Flask-Admin 'column_list' definition
        _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)

Note the helper methods to provide the actual summary data at lines 66 and 71, these need to be adjusted as necessary:

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()

Upvotes: 5

Related Questions