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

无法将Django贪吃蛇游戏分数关联至Admin模型,需实现排行榜

Django贪吃蛇游戏分数提交与排行榜实现修复方案

一、后端视图函数问题修复

当前视图存在三个核心问题:未处理匿名用户分数提交、返回格式与前端期望不匹配、缺少分数合法性校验。修复后代码如下:

from django.http import JsonResponse
from django.views.decorators.http import require_POST
import json

@require_POST
def submit_score(request):
    try:
        data = json.loads(request.body)
        score = data.get('score')
        
        # 校验分数是否为非负整数
        if not isinstance(score, int) or score < 0:
            return JsonResponse({'status': 'error', 'message': '无效的分数值'}, status=400)

        user = request.user if request.user.is_authenticated else None
        player_username = user.username if user else "匿名用户"

        new_score = Score(player=user, point=score, player_username=player_username)
        new_score.save()

        return JsonResponse({'status': 'success', 'message': '分数保存成功'})
    except json.JSONDecodeError:
        return JsonResponse({'status': 'error', 'message': '请求数据格式错误'}, status=400)

二、Score模型冗余字段优化

player_username字段可通过player关联获取,无需手动维护。可通过模型信号自动填充,避免代码冗余:

from django.db import models
from django.conf import settings
from django.db.models.signals import pre_save
from django.dispatch import receiver

class Score(models.Model):
    player = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True)
    point = models.IntegerField()
    player_username = models.CharField(max_length=30, default="匿名用户")

    def __str__(self):
        return f'{self.player_username} - {self.point}'

# 保存前自动填充用户名
@receiver(pre_save, sender=Score)
def auto_fill_username(sender, instance, **kwargs):
    if instance.player:
        instance.player_username = instance.player.username
    else:
        instance.player_username = "匿名用户"

优化后无需在视图中手动赋值player_username,减少重复逻辑。

三、前端JavaScript问题修复

当前代码缺少getCookie实现、相对路径可能出错且前端期望JSON但后端原返回文本,导致解析失败。修复后代码:

// 实现CSRF Token获取函数
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.startsWith(`${name}=`)) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

function submitScore(score) {
    // 使用根路径确保端点正确,根据实际URL调整
    fetch('/submit-score/', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': getCookie('csrftoken')
        },
        body: JSON.stringify({ score: score })
    })
    .then(response => {
        if (!response.ok) {
            throw new Error(`请求状态码: ${response.status}`);
        }
        return response.json();
    })
    .then(data => {
        console.log('分数保存结果:', data);
        // 可在此添加用户提示,比如弹窗显示成功/失败信息
    })
    .catch(error => {
        console.error('分数保存失败:', error);
    });
}

四、排行榜实现思路

编写视图获取排序后的分数列表,返回给前端渲染:

def leaderboard(request):
    # 按分数降序排序,取前50条记录
    top_scores = Score.objects.all().order_by('-point')[:50]
    leaderboard_data = [
        {'username': item.player_username, 'score': item.point}
        for item in top_scores
    ]
    return JsonResponse({'leaderboard': leaderboard_data})

前端通过fetch('/leaderboard/')获取数据后,动态渲染HTML表格或列表展示排行榜。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:31:07