Code Monkey home page Code Monkey logo

flask-admin-dashboard-summary's Introduction

Flask-Admin Dashboard With Summaries

Summary

This project was created in response to this SO question - Flask Admin Models - Summary row. The question references a previous SO question, How do you add a summary row for Flask-Admin?.

This project is a clone of Flask-Admin-Dashboard with an extra view (Projects) showing how to add summary rows to a Flask-Admin list view.

This project differentiates from the original:

  • Uses the new Flask methods for running the project
  • The database is initialized via a flask command create-database defined in commands.py
  • Database and models have been placed in models.py
  • Flask-Admin views have been placed in views.py

Initializing the database

The project comes with a pre-initialized database (sample_db.sqlite). To create a new database, from a CLI, in the root of the project run:

> flask create-database

Running Flask

From the CLI, in the root of the project run:

> flask run

 * Serving Flask app "app/__init__.py"
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

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

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

views.py beginning at line 60.

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 conditional check on the template as we're not concerned with the Edit/Create rendering and the injection of a summary_data dictionary into the method's **kwargs argument.

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

flask-admin-dashboard-summary's People

Contributors

dependabot[bot] avatar pjcunningham avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

flask-admin-dashboard-summary's Issues

Updating summary values on applying filters

I had a query regarding how to get the values of the summary change on applying the column_filters function. For example in your Project View,
column_filters = ['cost'], the values of both the summary rows don't change even on applying the filter. As I understand, the rows change if there is a change in the underlying data only but is it possible in my case?

list_template = 'admin/model/summary_list.html'
form_columns = ('name', 'cost')
page_size = 10
column_filters=['cost']

Column Filters in Dropdown form

I had a query regarding column filters.
I have a model called Data and corresponding view called Data View. I had used those in place of the Project and Project View in this repo so it has the summary rows as well. One of the columns of this model is 'Customer_Name'.By using the following code, I was able to add the filter to the view - column_filters=['Customer_Name] and is filtering perfectly. But here we need to type the name of the customer.
Instead of having to type the name, I would like it to be in dropdown form containing unique names of customers. I had found your SO answer : https://stackoverflow.com/questions/40626768/how-to-compute-options-of-dropdown-for-column-filter-in-flask-admin and have done the following.

def get_all_names():
    with app.app_context():
       unique_names = Data.query.with_entities(Data.Customer_Name.distinct().label('Customer_Name')).order_by(Data.Customer_Name.asc()).all()
        return [(cust.Customer_Name,cust.Customer_Name) for cust in unique_names]

class DataView(MyModelView):
  column_filters=[
        FilterEqual(column=Data.Customer_Name,name='Customer Name',options=get_all_names),
    ]

It is showing up the "equals" and a textbox beside it instead of dropdown.
How do I go about this?

Thank you so much.

Hey, I'm the guy from SO that created this issue.

First of all, thank you so much, I've already been able to implement this into my project.

I seriously can't thank you enough for this, really made my day.

Not trying to abuse you, could I just ask you two more questions?

Thank's again!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.