题目:
使用django建立一个玩家分数排行榜服务,服务项客户端提供两个接口:
1. 客户端上传客户端号和分数(注意:并不会上传排名,客户端无法上传排名),同一个客户端可以多次上传分数,取最新的一次分数
2. 客户端查询排行榜
例子说明
· 10个客户端分别调用一次接口1,分数范围1^10000000
· 其中底个客户端调用一次接口2,输出为下图所示 接口2说明
· 可以查询任何名次段,例如可以查询20~30的表格
· 每次查询最后都要附加上调用接口的客户端的排名,如例子所示客户端5的排名被附加到了最后
![d974b529cf879f7f4fe14ba9f4dcc010.jpeg](https://i-blog.csdnimg.cn/blog_migrate/6415da1b3236383a871013584ec9a5d4.jpeg)
![c2f6895a25d19d3165657526f9f7666e.png](https://i-blog.csdnimg.cn/blog_migrate/a0ef9d87ec82a5ce24e2976e9cd9af56.png)
任务说明
·自己设计接口地址,参数,返回值并实现接口题目:
以下是主要实现:两个接口分别对应 "upload/" (上传)和 "show/"(查询展示);数据库模型建立了两张表,一张表存储客户端号和其所上传的分数,另一张表记录名次,并且与分数表的客户端id一对一关系。由于名次是在每次上传或者更新分数时都会跟新的,所以用单独一张表存储方便处理。对于查询页面,第一次进入该页面默认显示全部的排名,后期如果数据量过大的时候可调整为只展示排名靠前的,具体多少名可根据需求更改,点击下方查询后会展示删选条件区间内的排名情况。
![6e8a4af4f9d8a991ae2054c1c33af56a.jpeg](https://i-blog.csdnimg.cn/blog_migrate/d049e249c168d383d4107b8dc2c6e229.jpeg)
![2cffb5ce6033b3ca2359cd2f6b4a7f00.jpeg](https://i-blog.csdnimg.cn/blog_migrate/8a2c1cead3fac30ed6332a25013fb51e.jpeg)
![9eb453fc8ca2424eeb859586d8dd7b99.jpeg](https://i-blog.csdnimg.cn/blog_migrate/a3c59847d9caaf4f351cfa7c7b5fe209.jpeg)
代码如下:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('demo1.urls')),
]
demo1/urls.py
from django.urls import path, include
from . import views
app_name = 'demo1'
urlpatterns = [
path('', views.login, name='login'),
path('logout/', views.logout, name='logout'),
path('upload/', views.upload, name='upload'),
path('show/', views.show, name='show'),
]
demo1/models.py
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
# Create your models here.
# 分数表
class Score(models.Model):
client = models.CharField(verbose_name='客户端号', max_length=16, unique=True)
score = models.IntegerField(verbose_name='分数', default=0,
validators=[MaxValueValidator(10000000), MinValueValidator(1)])
def __str__(self):
return f'{self.client}'
class Meta:
verbose_name = '分数登记表'
verbose_name_plural = verbose_name
# 名次表
class Rank(models.Model):
c_id = models.OneToOneField(Score, on_delete=models.CASCADE,primary_key=True,)
rank = models.IntegerField(verbose_name='名次', validators=[MinValueValidator(1)])
demo1/views.py
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from demo1.models import Score,Rank
# Create your views here.
# 登陆
@csrf_exempt
def login(request):
if request.method == 'GET':
return render(request, 'demo1/login.html')
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password) # 根据获取的用户名密码去数据库查询,并返回user对象
if user is not None and user.is_active:
auth.login(request, user)
return redirect('upload/')
else:
return render(request, 'demo1/login.html')
# 登出
def logout(request):
auth.logout(request) # 从请求中删除经过身份验证的用户的ID并刷新其会话数据。
return redirect('/')
@login_required(login_url='/')
@csrf_exempt
def upload(request):
if request.method == 'GET':
return render(request, 'demo1/upload.html', {'user': request.user, })
if request.method == 'POST':
# 接受页面上传的数据
score = request.POST.get('score', '')
if score:
# 获取数据库的数据
old_scor = Score.objects.filter(client=request.user).first()
if old_scor:
if old_scor.score != score:
old_scor.score=score
old_scor.save()
else:
Score.objects.create(client=request.user, score=score)
# 排名表数据更新
Rank.objects.all().delete()
score_li =[score_obj.id for score_obj in Score.objects.all().order_by('-score')]
n=1
for i in score_li:
Rank.objects.create(c_id_id=i,rank=n)
n=n+1
return JsonResponse({'status': 'sucess'})
return JsonResponse({'status': 'error'})
@login_required(login_url='/')
@csrf_exempt
def show(request):
context = {'scores': [{'ranking':scor.rank.rank , 'client': scor.client, 'score':scor.score } for scor in Score.objects.all().order_by('-score')]}
if request.method == 'GET':
count = Score.objects.all().count()
uscore =Score.objects.filter(client=request.user).first()
uscore ={'ranking':uscore.rank.rank,'score':uscore.score}
return render(request, 'demo1/show.html',{'context':context,'count':count,'uscore':uscore})
if request.method == 'POST':
try:
start =int(request.POST.get('start'))
end = int(request.POST.get('end'))
except ValueError as e1:
return JsonResponse({'status': 'error'})
context = {'scores': [{'ranking': scor.rank.rank, 'client': scor.client, 'score': scor.score} for scor in
Score.objects.all().order_by('-score')[start-1:end]]}
return JsonResponse({'status': 'ok', 'context': context})
upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传</title>
</head>
<body>
<form method="post">
<h3>
当前客户端 {{ user }},请上传分数:<input type="text" id="score" name="score" placeholder="可输入范围:1~10000000。"> 分。
<input name="" type="button" value="提交" onclick="return sub()"/><div id="score_err" style="color: red;"></div>
<div id="score_err" style="color: red;"></div>
</h3>
</form>
<a href="{% url 'demo1:show' %}"><input name="" type="button" value="查询"/></a>
<a href="/logout/"><input name="" type="button" value="退出"/></a>
<script language="JavaScript" src="/static/js/jquery-1.12.3.min.js"></script>
<script type="text/javascript">
function sub() {
var score = $('#score').val();
var flag = true;
if (score < 1 || score > 10000000) {
$('#score_err').text('分数不符合规范!');
flag = false;
}
if (flag) {
$.ajax({
url: '/upload/',
data: {'score': score},
type: 'POST',
success: function (result) {
alert(result.status)
}
})
}
return flag;
}
</script>
</body>
</html>
show.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>查询</title>
</head>
<body>
<a href="{% url 'demo1:upload' %}"><input name="" type="button" value="上传页面"/></a>
<a href="/logout/"><input name="" type="button" value="退出"/></a>
<div id="table1">
<table border="1px" width="300px" cellspacing="0px" align="center">
<thead>
<tr>
<th>排名</th>
<th>客户端</th>
<th>分数</th>
</tr>
</thead>
<tbody>
{% for item in context.scores %}
<tr>
<td>{{ item.ranking }}</td>
<td>{{ item.client }}</td>
<td>{{ item.score }}</td>
</tr>
{% endfor %}
<tr>
<td>{{ uscore.ranking }}</td>
<td>{{ user }}</td>
<td>{{ uscore.score }}</td>
</tr>
</tbody>
</table>
</div>
<h5>请输入要查询名次范围:第
<input type="text" id="start" name="start" placeholder="请输入起始名次,例如:10">
至
<input type="text" id="end" name="end" placeholder="请输入终止名次,例如:20">名。
<input name="submit" id="submit" type="button" value="查询" onclick="return f()"/>
</h5>
<div id="start_err" style="color: red;"></div>
<div id="end_err" style="color: red;"></div>
<div id="table2" style="display: none">
<table border="1px" width="300px" cellspacing="0px" align="center">
<thead>
<tr>
<th>排名</th>
<th>客户端</th>
<th>分数</th>
</tr>
</thead>
<tbody id="tbody2"></tbody>
<tr>
<td>{{ uscore.ranking }}</td>
<td>{{ user }}</td>
<td>{{ uscore.score }}</td>
</tr>
</table>
</div>
<script language="JavaScript" src="/static/js/jquery-1.12.3.min.js"></script>
<script type="text/javascript">
var context2;
function f() {
var start = $('#start').val();
var end = $('#end').val();
var flag = true;
if (start < 0) {
$('#start_err').text('起始名次不支持负数!');
flag = false;
}
if (end < 0) {
$('#end_err').text('终止名次不支持负数!');
flag = false;
}
if (flag) {
$.ajax({
url: '/show/',
data: {'start': start, 'end': end},
type: 'POST',
success: function (result) {
if (result['status']=='ok'){
$('#table1').hide();
$('#table2').show();
context2 = result['context'];
$("#tbody2").empty();
$.each(context2['scores'], function (index, item) {
$('#tbody2').append('<tr><td>' + item['ranking'] + '</td><td>' +
item['client'] + '</td><td>' + item['score'] + '</td></tr>');
});
}else{
alert('请输入合法的名次!名次为数值型且为整数。')
}
},
})
}
return flag;
}
</script>
</body>
</html>