【问题标题】:How to go to the last page of paginated Flask-Admin view by default.. without sorting descending默认情况下如何转到分页的 Flask-Admin 视图的最后一页.. 不降序排序
【发布时间】:2021-03-24 18:38:09
【问题描述】:

在用于数据库表查看/管理的 Python Flask-Admin 中,我需要视图自动打开到分页数据的最后一页。

重要提示:我不能简单地对记录进行降序排序,所以最后一条记录首先显示。

下面是我的简单示例。我希望它从最后一页开始,如图所示。

这里有一些示例代码来重现我的模型:

import os
import os.path as op
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

import flask_admin as admin
from flask_admin.contrib.sqla import ModelView


# Create application
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_db2.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)


# Models
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Unicode(64))
    email = db.Column(db.Unicode(64))

    def __unicode__(self):
        return self.name


class UserAdmin(ModelView):
    column_searchable_list = ('name', 'email')
    column_editable_list = ('name', 'email')
    column_display_pk = True

    can_set_page_size = True
    # the number of entries to display in the list view
    page_size = 5


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


admin = admin.Admin(app, 'Example', template_mode='bootstrap3')

# Add views
admin.add_view(UserAdmin(User, db.session))


def build_sample_db():
    """
    Populate a small db with some example entries.
    """

    db.drop_all()
    db.create_all()

    first_names = [
        'Harry', 'Amelia', 'Oliver', 'Jack', 'Isabella', 'Charlie','Sophie', 'Mia',
        'Jacob', 'Thomas', 'Emily', 'Lily', 'Ava', 'Isla', 'Alfie', 'Olivia', 'Jessica',
        'Riley', 'William', 'James', 'Geoffrey', 'Lisa', 'Benjamin', 'Stacey', 'Lucy'
    ]
    last_names = [
        'Brown', 'Smith', 'Patel', 'Jones', 'Williams', 'Johnson', 'Taylor', 'Thomas',
        'Roberts', 'Khan', 'Lewis', 'Jackson', 'Clarke', 'James', 'Phillips', 'Wilson',
        'Ali', 'Mason', 'Mitchell', 'Rose', 'Davis', 'Davies', 'Rodriguez', 'Cox', 'Alexander'
    ]

    for i in range(len(first_names)):
        user = User()
        user.name = first_names[i] + " " + last_names[i]
        user.email = first_names[i].lower() + "@example.com"
        db.session.add(user)

    db.session.commit()
    return


if __name__ == '__main__':

    # Build a sample db on the fly, if one does not exist yet.
    app_dir = op.realpath(os.path.dirname(__file__))
    database_path = op.join(app_dir, app.config['DATABASE_FILE'])
    if not os.path.exists(database_path):
        build_sample_db()

    # Start app
    app.run(debug=True, host='0.0.0.0')

【问题讨论】:

    标签: python flask pagination flask-admin


    【解决方案1】:

    我找到了解决问题的理想方法,覆盖了flask_admin.contrib.sqla.ModelView 类中的index_view() 模板渲染视图方法。

    class UserAdmin(ModelView):
        column_searchable_list = ('name', 'email')
        column_editable_list = ('name', 'email')
        column_display_pk = True
    
        can_set_page_size = True
        # the number of entries to display in the list view
        page_size = 5
    
        # Now to override the index_view method
        @expose('/')
        def index_view(self):
            """List view overridden to DEFAULT to the last page, 
            if no other request args have been submitted"""
    
            if self.can_delete:
                delete_form = self.delete_form()
            else:
                delete_form = None
    
            # Grab parameters from URL
            view_args = self._get_list_extra_args()
    
            # Map column index to column name
            sort_column = self._get_column_by_idx(view_args.sort)
            if sort_column is not None:
                sort_column = sort_column[0]
    
            # Get page size
            page_size = view_args.page_size or self.page_size
    
            #####################################################################
            # Custom functionality to start on the last page instead of the first
    
            if len(request.args) == 0:
                # Standard request for the first page (no additional args)
                count_query = self.get_count_query() if not self.simple_list_pager else None
                # Calculate number of rows if necessary
                count = count_query.scalar() if count_query else None
                # Calculate number of pages
                if count is not None and page_size:
                    num_pages = int(ceil(count / float(page_size)))
                    # Change the page to the last page (minus 1 for zero-based counting)
                    setattr(view_args, 'page', num_pages - 1)
    
            # End of custom code. The rest below is from the Flask-Admin package
            ############################################################################
    
            # Get database data for the view_args.page requested
            count, data = self.get_list(view_args.page, sort_column, view_args.sort_desc,
                                        view_args.search, view_args.filters, page_size=page_size)
    
            list_forms = {}
            if self.column_editable_list:
                for row in data:
                    list_forms[self.get_pk_value(row)] = self.list_form(obj=row)
    
            # Calculate number of pages
            if count is not None and page_size:
                num_pages = int(ceil(count / float(page_size)))
            elif not page_size:
                num_pages = 0  # hide pager for unlimited page_size
            else:
                num_pages = None  # use simple pager
    
            # Various URL generation helpers
            def pager_url(p):
                # Do not add page number if it is first page
                if p == 0:
                    p = None
    
                return self._get_list_url(view_args.clone(page=p))
    
            def sort_url(column, invert=False, desc=None):
                if not desc and invert and not view_args.sort_desc:
                    desc = 1
    
                return self._get_list_url(view_args.clone(sort=column, sort_desc=desc))
    
            def page_size_url(s):
                if not s:
                    s = self.page_size
    
                return self._get_list_url(view_args.clone(page_size=s))
    
            # Actions
            actions, actions_confirmation = self.get_actions_list()
            if actions:
                action_form = self.action_form()
            else:
                action_form = None
    
            clear_search_url = self._get_list_url(view_args.clone(page=0,
                                                                  sort=view_args.sort,
                                                                  sort_desc=view_args.sort_desc,
                                                                  search=None,
                                                                  filters=None))
    
            return self.render(
                self.list_template,
                data=data,
                list_forms=list_forms,
                delete_form=delete_form,
                action_form=action_form,
    
                # List
                list_columns=self._list_columns,
                sortable_columns=self._sortable_columns,
                editable_columns=self.column_editable_list,
                list_row_actions=self.get_list_row_actions(),
    
                # Pagination
                count=count,
                pager_url=pager_url,
                num_pages=num_pages,
                can_set_page_size=self.can_set_page_size,
                page_size_url=page_size_url,
                page=view_args.page,
                page_size=page_size,
                default_page_size=self.page_size,
    
                # Sorting
                sort_column=view_args.sort,
                sort_desc=view_args.sort_desc,
                sort_url=sort_url,
    
                # Search
                search_supported=self._search_supported,
                clear_search_url=clear_search_url,
                search=view_args.search,
                search_placeholder=self.search_placeholder(),
    
                # Filters
                filters=self._filters,
                filter_groups=self._get_filter_groups(),
                active_filters=view_args.filters,
                filter_args=self._get_filters(view_args.filters),
    
                # Actions
                actions=actions,
                actions_confirmation=actions_confirmation,
    
                # Misc
                enumerate=enumerate,
                get_pk_value=self.get_pk_value,
                get_value=self.get_list_value,
                return_url=self._get_list_url(view_args),
    
                # Extras
                extra_args=view_args.extra_args,
            )
    

    【讨论】:

      【解决方案2】:

      下面的想法怎么样:

      # Flask views
      @app.route('/')
      def index():
          # from sqlalchemy import func
          # n=(db.session.query(func.count(User.id)).all())[0][0]
          # or
          n=len(User.query.all())
          last_page=int((n-1)/UserAdmin.page_size)
          return f'<a href="/admin/user/?page={last_page}">Click me to get to Admin!</a>'
      

      【讨论】:

      • 这是在管理索引视图中创建特殊链接的绝佳选择,但我希望在从导航栏菜单请求视图时创建默认链接
      猜你喜欢
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 2019-10-10
      • 2020-08-31
      • 2017-10-14
      • 2017-03-04
      • 2015-08-22
      • 2019-01-19
      相关资源
      最近更新 更多