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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:15:09