You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django列表页实现点击加载更多数据按钮无页面重载的方案

问题描述

我正在用Django结合Riot API开发一款英雄联盟相关数据展示网站,其中有一个页面用来展示被搜索玩家的历史对局记录。如果初始加载时就拉取每一局对局的全部详细数据,会导致页面加载耗时过长,所以我想做一个按钮,点击后可以在当前页面无刷新展示对应对局的深度数据。

我前端开发经验不多,当前页面效果如下:
当前页面效果

现有views.py代码

def user_info(request, server, summoner_name, template='riot/user-profile.html'):
    account_id = user_account_info['accountId']
    games_list = api_interaction.get_past_games(server, account_id)
    champ_json = services.load_champ_json_session(request)
    game_summary_list = services.get_game_summary_list(games_list, champ_json)
    context = {
        'game_summary_list': game_summary_list,
        'user_account_info': user_account_info, 
        'summoner_stats': summoner_stats 
    }
    if ('load') in request.POST:
        gameId = (request.POST['load'])
        game_data = api_interaction.game_summary(server, gameId, champ_json)
        context['game_data'] = game_data
        return render(request, template, context)
    else:
        return render(request, template, context)

现有模板代码

我的实现逻辑是点击按钮提交表单,views.py检测到表单提交后处理相关数据,把额外数据塞进上下文返回。模板对应代码如下:

{% for game in game_summary_list %}
    <span class="anchor" id="{{forloop.counter}}"></span>
    <div class="container" style="border:1px solid rgb(64, 97, 71);">
        <br>
        <h4><a href="/{{user_account_info.server}}/{{user_account_info.name}}/{{game.champion_name}}">{{ game.champion_name }}</a> {{game.position}} {{game.date}} {{ game.game_id}}</h4>

        <form action="#{{forloop.counter}}" method="post">
        {% csrf_token %}
        <button name="load" type="submit" value="{{game.game_id}}" class="btn btn-info">Show game summary</button>
        </form>
        <br>
        
        <div id="load_more">
            {% if game_data.success %}
            {% if game_data.game_id == game.game_id %}
                <table class="table table-bordered">
                <thead>
                    <tr>
                        <th scope="col">Game ID</th>
                        <th scope="col">服务器</th>
                        <th scope="col">对局时间</th>
                        <th scope="col">对局时长</th>
                        <th scope="col">游戏模式</th>
                        <th scope="col">游戏版本</th>
                    </tr>
                </thead>
        
                <tbody>
                    <tr>
                        <td>{{ game_data.gameId }}</td>
                        <td>{{ game_data.platformId }}</td>
                        <td>{{ game_data.gameCreation }}</td>
                        <td>{{ game_data.gameDuration }}</td>
                        <td>{{ game_data.gameMode }}</td>
                        <td>{{ game_data.gameVersion }}</td>
                    </tr>
                </tbody>
        
                <thead>
                    <tr>
                        <th scope="col">{{ game_data.teams.0.win }} (蓝队)</th>
                        <th scope="col">段位</th>
                        <th scope="col">KDA</th>
                        <th scope="col">伤害</th>
                        <th scope="col">补刀</th>
                        <th scope="col">视野得分</th>
                    
                    </tr>
                </thead>
                
                <tbody>
                    {% for player in game_data.participants|slice:":5" %}
                    <tr >
                        <td>{{ player.champion_name }}/<a href="/{{user_account_info.server}}/{{player.summoner_name}}"> {{ player.summoner_name }}</a></td>
                        <td>{{ player.tier }}</a></td>
                        <td>{{ player.stats.kills }}/{{ player.stats.deaths }}/{{ player.stats.assists }}</td>
                        <td>{{ player.stats.totalDamageDealtToChampions }}</td>
                        <td>{{ player.stats.totalMinionsKilled }}</td>
                        <td>{{ player.stats.visionScore }}</td>
                    </tr>
                    {% endfor %}
                </tbody>
        
                <thead>
                    <tr>
                        <th scope="col">{{ game_data.teams.1.win }} (红队)</th>
                        <th scope="col">段位</th>
                        <th scope="col">KDA</th>
                        <th scope="col">伤害</th>
                        <th scope="col">补刀</th>
                        <th scope="col">视野得分</th>
                    
                    </tr>
                </thead>
                
                <tbody>
                    {% for player in game_data.participants|slice:"5:" %}
                        <tr>
                        <td>{{ player.champion_name }}/<a href="/{{user_account_info.server}}/{{player.summoner_name}}"> {{ player.summoner_name }}</a></td>
                        <td>{{ player.tier }}</a></td>
                        <td>{{ player.stats.kills }}/{{ player.stats.deaths }}/{{ player.stats.assists }}</td>
                        <td>{{ player.stats.totalDamageDealtToChampions }}</td>
                        <td>{{ player.stats.totalMinionsKilled }}</td>
                        <td>{{ player.stats.visionScore }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
                </table>
                <br>
            {% endif %}
            {% endif %}
        </div>
    </div>
    <br>
{% endfor %}

点击按钮后的页面效果如下:
点击后页面效果

现在功能可以正常运行,但问题是用户点击「Show game summary」按钮时页面会重载。我通过给每个对局div加id、表单提交后跳转到对应div的方式临时解决了定位问题,但还是想要实现无刷新加载展示数据,不确定用表单实现这个需求是不是正确的方向。


解决方案

1. 修改按钮触发逻辑

把提交表单的按钮改成点击调用JS函数:

<button onclick="loadGameData('{{game.game_id}}')">Show game summary</button>

2. 新增预定义隐藏表格

创建默认隐藏的空表格,提前定义好各个thead和tbody的id:

<table style="display: none" id="game-{{game.game_id}}" class="table table-bordered">
  <thead id='game-{{game.game_id}}-thead-general'>
  </thead>
  <tbody id='game-{{game.game_id}}-tbody-general'>
  </tbody>
  <thead id='game-{{game.game_id}}-thead-blue'>
  </thead>
  <tbody id='game-{{game.game_id}}-tbody-blue'>
  </tbody>
  <thead id='game-{{game.game_id}}-thead-red'>
  </thead>
  <tbody id='game-{{game.game_id}}-tbody-red'>
  </tbody>
</table>

3. 新增AJAX请求逻辑

用JS发送异步请求拉取数据,动态生成表格内容:
注意:代码依赖jQuery,需要提前在页面引入jQuery库

<script type="text/javascript">
function loadGameData(gameId) {
    $.ajax({
        url : gameId, // 替换成你自己的后端接口地址
        method: "GET",
        error: function(xhr, status, error) {
          alert("服务器错误");
      },
        success: function(gameJson){

            $('#game-'+ gameId + '-thead-general').append('<tr><th> 对局ID </th>'
                                                          + '<th> 服务器 </th>'
                                                          + '<th> 对局时间 </th>'
                                                          + '<th> 时长 </th>'
                                                          + '<th> 模式 </th>'
                                                          + '<th> 版本 </th></tr>')

            $('#game-'+ gameId + '-tbody-general').append('<tr><td>' + gameJson.gameId + '</td>'
                                                            + '<td>' + gameJson.platformId + '</td>'
                                                            + '<td>' + gameJson.gameCreation + '</td>'
                                                            + '<td>' + gameJson.gameDuration + '</td>'
                                                            + '<td>' + gameJson.gameMode + '</td>'
                                                            + '<td>' + gameJson.gameVersion + '</td></tr>')
                                                            
            $('#game-'+ gameId + '-thead-blue').append('<tr><th>' + gameJson.teams[0].win + ' (蓝队) </th>'
                                                        + '<th> 段位 </th>'
                                                        + '<th> KDA </th>'
                                                        + '<th> 伤害 </th>'
                                                        + '<th> 补刀 </th>'
                                                        + '<th> 视野得分 </th></tr>')
                                                        
            gameJson.participants.slice(0,5).forEach(participant => $('#game-'+ gameId + '-tbody-blue').append('<tr><td>' + participant.champion_name + ' ' + participant.summoner_name + '</td>'
                                                                                                            + '<td>' + participant.tier +  '</td>'
                                                                                                            + '<td>' +  participant.stats.kills + '/' +  participant.stats.deaths + '/' +  participant.stats.assists + '</td>'
                                                                                                            + '<td>' + participant.stats.totalDamageDealtToChampions + '</td>'
                                                                                                            + '<td>' + participant.stats.totalMinionsKilled + '</td>'
                                                                                                            + '<td>' + participant.stats.visionScore + '</td></tr>'))
            $('#game-'+ gameId + '-thead-red').append('<tr><th>' + gameJson.teams[1].win + ' (红队) </th>'
                                                        + '<th> 段位 </th>'
                                                        + '<th> KDA </th>'
                                                        + '<th> 伤害 </th>'
                                                        + '<th> 补刀 </th>'
                                                        + '<th> 视野得分 </th></tr>')
            gameJson.participants.slice(5,10).forEach(participant => $('#game-'+ gameId + '-tbody-red').append('<tr><td>' + participant.champion_name + ' ' + participant.summoner_name + '</td>'
                                                                                                            + '<td>' + participant.tier +  '</td>'
                                                                                                            + '<td>' +  participant.stats.kills + '/' +  participant.stats.deaths + '/' +  participant.stats.assists + '</td>'
                                                                                                            + '<td>' + participant.stats.totalDamageDealtToChampions + '</td>'
                                                                                                            + '<td>' + participant.stats.totalMinionsKilled + '</td>'
                                                                                                            + '<td>' + participant.stats.visionScore + '</td></tr>'))
            $('#game-'+gameId).show()
        }
    });
}
</script>

4. 新增后端接口

首先在urls.py中新增路由,匹配AJAX请求的地址:

path('game/data/', views.getGameData, name="getGameData"),

然后在views.py中新增对应接口函数,返回JSON格式的对局数据:

from django.http import JsonResponse

def getGameData(request):
    # 此处复用你之前user_info里的对局数据查询逻辑即可
    server = request.GET.get('server')
    game_id = request.GET.get('game_id')
    champ_json = services.load_champ_json_session(request)
    game_data = api_interaction.game_summary(server, game_id, champ_json)
    return JsonResponse(game_data)

内容的提问来源于stack exchange,提问作者overscepticism

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 21:21:03