如何将JavaScript游戏分数提交至Django Ranking模型?
解决Django中游戏高分存储问题
1. 完善Ranking模型
你的Ranking模型缺少与具体游戏的关联,无法区分不同游戏的高分,先更新模型:
class Ranking(models.Model): player = models.ForeignKey(User, on_delete=models.CASCADE) game = models.ForeignKey(Game, on_delete=models.CASCADE) # 新增游戏关联 game_overall_score = models.IntegerField(null=True) # 约束一个用户对应单款游戏仅存一条记录 class Meta: unique_together = ('player', 'game')
修改后执行迁移命令:
python manage.py makemigrations python manage.py migrate
2. 修改模板隐藏表单
添加隐藏输入框存储分数,让表单提交时能传递分数数据:
<form id="score-form" action="/games/{{ game.slug }}" method="post"> {% csrf_token %} <!-- 新增隐藏字段用于传递分数 --> <input type="hidden" id="score-input" name="game_score" value="0"> <button type="submit" id="submit-score" hidden>上传高分到排行榜</button> </form>
3. 编写视图处理POST请求
在loadGame视图中处理分数提交,确保仅登录用户能操作,并实现“只存最高分”的逻辑:
from django.contrib.auth.decorators import login_required @login_required # 限制仅登录用户提交 def loadGame(request, slug): game = Game.objects.get(slug=slug) if request.method == 'POST': # 获取提交的分数并转为整数 submitted_score = int(request.POST.get('game_score', 0)) # 查找用户当前游戏的记录,无则创建 ranking, is_new = Ranking.objects.get_or_create( player=request.user, game=game, defaults={'game_overall_score': submitted_score} ) # 已有记录时,仅更新更高的分数 if not is_new and submitted_score > ranking.game_overall_score: ranking.game_overall_score = submitted_score ranking.save() # 可添加提交成功提示,这里直接返回原页面 return render(request, 'main/game-detail.html', {'game': game, 'score_saved': True}) return render(request, 'main/game-detail.html', {'game': game})
4. JavaScript处理分数提交
在游戏逻辑的合适时机(比如游戏结束),将分数赋值给表单并触发提交:
var score = 0; ... // 游戏结束逻辑(比如碰撞触发) if (pipes[i].hits(bird)) { submitScore(); // 提交当前分数 score = 0; pipes = []; return; } ... if (frameCount % 5 == 0) { score++; } // 新增分数提交函数 function submitScore() { // 将当前分数赋值给隐藏输入框 document.getElementById('score-input').value = score; // 触发表单提交 document.getElementById('score-form').submit(); } // 若需手动提交,可添加可见按钮绑定事件: // <button onclick="submitScore()">上传我的高分</button>
可选:无刷新AJAX提交
如果不想刷新页面,用原生JS实现AJAX提交:
function submitScore() { const scoreInput = document.getElementById('score-input'); scoreInput.value = score; const form = document.getElementById('score-form'); const formData = new FormData(form); fetch(form.action, { method: 'POST', body: formData, headers: { 'X-CSRFToken': form.querySelector('[name=csrfmiddlewaretoken]').value } }) .then(response => response.json()) .then(data => { console.log('高分保存成功'); // 可添加前端提示,比如弹出消息 }) .catch(error => { console.error('提交失败:', error); }); }
同时修改视图返回JSON响应:
from django.http import JsonResponse @login_required def loadGame(request, slug): game = Game.objects.get(slug=slug) if request.method == 'POST': submitted_score = int(request.POST.get('game_score', 0)) ranking, is_new = Ranking.objects.get_or_create( player=request.user, game=game, defaults={'game_overall_score': submitted_score} ) if not is_new and submitted_score > ranking.game_overall_score: ranking.game_overall_score = submitted_score ranking.save() return JsonResponse({'status': 'success', 'current_highscore': ranking.game_overall_score}) return render(request, 'main/game-detail.html', {'game': game})
内容的提问来源于stack exchange,提问作者Mr Professor
相关产品推荐
相关产品推荐

