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
相关产品推荐
相关产品推荐

