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

