python Flask-Sqlalchemy分页-当同一页上有多个表时如何对表进行分页

6tr1vspr  于 2023-01-12  发布在  Python
关注(0)|答案(2)|浏览(136)

我希望在同一页上有多个表,并能够通过这些表单独分页。目前,如果我单击“下一步”转到表的下一页结果,则该页上的所有表都将转到下一页。如果表的页数不同,则会出现问题,因为页数较少的表将导致404错误。编辑:我刚刚意识到,如果我在分页参数中设置error_out=False,它不会对我产生404,而只是为较短的表提供一个空表。
我正在使用flak-sqlalchemy来查询支持工单表,并通过支持座席所属的support_team进行过滤。
以下是我的路线:

@interaction_bp.route("/my_teams_tix/")
def my_teams_tix():
    user = User.query.filter_by(full_name=str(current_user)).first()  # get the current user
    teams = user.teams # a list of all the teams the current user is in

    page = request.args.get('page', 1, type=int)
    tickets = {}

    for team in teams:
        team_ticket = (
            Ticket.query.filter(Ticket.support_team_id == team)
            .filter(Ticket.status != "Closed")
            .order_by(Ticket.ticket_number.asc())
            .paginate(page=page, per_page=current_app.config["ROWS_PER_PAGE"]) # this is 5
        )
        tickets[team.name] = team_ticket

    return render_template('interaction/my_teams_work.html', tickets=tickets

这将列出分配给当前用户所在团队的所有票证。
我使用了一个jinja 2模板,如下所示(为了简化这个例子,去掉了所有的css代码和大部分字段):

{% for team, pagination in tickets.items() %}
<h2>{{ team }}</h2>
<table id="{{team}}-table">
    <thead>
        <tr>
            <th>Ticket ID</th>
            <th>Title</th>
            <th>Owner</th>
        </tr>
    </thead>
    <tbody>
        {% for ticket in pagination.items %}
        <tr>
            <td>{{ ticket.ticket_number }}</td>
            <td>{{ ticket.type }}</td>
            <td>{{ ticket.supporter.name }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>

{% if pagination.has_prev %}
<a href="{{ url_for('interaction_bp.my_teams_tix', team_name=team, page=pagination.prev_num) }}">Previous</a>
{% endif %}

Page {{ pagination.page }} of {{ pagination.pages }}

{% if pagination.has_next %}
<a href="{{ url_for('interaction_bp.my_teams_tix', team_name=team, page=pagination.next_num) }}">Next</a>
{% endif %}

{% endfor %}

在这个例子中,用户是两个团队的成员,所以我最终得到了两个票证表,如下所示:

ITSM
Ticket ID   Title   Owner
1006    Incident    
1012    Request 
1013    Incident    
1015    Request 
1016    Request 
Page 1 of 3 Next

Database Admin
Ticket ID   Title   Owner
1001    Incident    
1007    Request 
1008    Incident    
1010    Incident    
1014    Request 
Page 1 of 2 Next

上面的第一个“Next”链接是这样的

http://localhost:5000/my_teams_tix/?team_name=ITSM&page=2

另一个是

http://localhost:5000/my_teams_tix/?team_name=Database+Admin&page=2

当我在任何一个表上单击“下一步”时,它会将两个表都移动到下一页。由于一个表有3页,其他2页,当我为有3页的表单击“下一步”时,我会得到404错误。
我希望将所有这些表格放在同一页上(根据支持代理所属的团队数量,可能会有4或5个表格),并对它们进行独立分页。
我的直觉告诉我,我需要用javascript来做,但我不知道如何去做。任何帮助都很感激。

6ojccjat

6ojccjat1#

我可能会尝试通过url编码独立管理每个分页表的状态,类似于您目前正在做的事情。
每次你运行这个程序,url_for都会清除掉所有以前的url编码,如果你想避免javascript,你需要重构这个程序来使用当前的URL,因为你会有多个表和单独的页面。

<a href="{{ url_for('interaction_bp.my_teams_tix', team_name=team, page=pagination.prev_num) }}">Previous</a>

它会清除另一个表的状态,为了避免javascript,你需要找到一种方法来维护当前的URL,这样你就可以嵌套每个不同表的分页状态。Flask- multiple paginations on same page
也就是说,如果您的表不是那么大,我可能只考虑转储整个DB响应,并让像DataTables这样的JS插件为您处理:https://datatables.net/

oprakyz7

oprakyz72#

经过反复试验,我找到了解决问题的方法,但这可能不是最好的方法,所以我仍在学习中,任何改进的建议都是值得赞赏的。
我最初的问题是我有支持票。这些支持票有一个支持代理。支持代理是一个或多个团队的成员,这可以是任何数字,他们可能在2个或10个不同的团队。
我想显示一个页面,其中包含一个单独的表,用于记录票证分配到的每个团队的所有票证。当前用户可能是也可能不是支持代理,但他们将能够查看分配到其所属团队的所有票证。
我不会展示这些模型,因为你可能已经知道了。因此,基于这种理解,我的路线如下:

@interaction_bp.get("/_my_teams_work/")
def my_teams_work():
    """
    calls my_teams_dashboard(model) where model is Ticket defined in common_utils.py to get list
    of all open tickets owned by the current user
    :return: renders template with table of all tickets owned by logged-in user
    """
    tickets = {}
    form = TicketForm()
    page = request.args.get("page", 1, type=int)  # for pagination of table
    page_team = request.args.get("team","all")

    highest_number = get_highest_ticket_number(Ticket) - 1
    teams = my_teams()

    for team in teams:
        team_ticket = my_teams_dashboard(Ticket, 1, team)
        tickets[team.name] = team_ticket
        if page_team == team.name:
            team_ticket = my_teams_dashboard(Ticket, page, team)
            # |= is the Update operator for dictionaries. This will update the value of ticket[team] with the new pagination
            # whilst keeping the existing entries as they are.
            tickets |= {team.name: team_ticket}

    return render_template(
        "/interaction/my-team.html",
        title="My Teams Work",
        subtitle=f"Open tickets for all {current_user}'s teams",
        teams=teams,
        teams_tickets=tickets,
        highest_number=highest_number,
        search_model="interaction",
        form=form,
    )

以下是提供票证的函数:

def my_teams():
    user = User.query.filter_by(
        full_name=str(current_user)
    ).first()  # get the current user

    teams = user.teams
    return teams

def my_teams_dashboard(model, page, team):
    team_ticket = (
            model.query.filter(
                and_(
                    model.supporter == current_user,
                    model.status != "Closed",
                    model.status != "Resolved",
                    model.support_team == team,
                )
            )
            .order_by(model.ticket_number)
            .paginate(page=page, per_page=current_app.config["ROWS_PER_PAGE"], error_out=False)
    )
    return team_ticket

我希望这对有同样问题的人有帮助。

相关问题