基于Django的打分系统
2020-03-07 本文已影响0人
lm_is_dc
Django项目之个人网站
Github地址:https://github.com/liangdongchang/MyWeb.git
感兴趣的可以fork或star一下
image功能模块三:打分
一、说明
功能:用户对进行分享的同学打分、留言。
用户点击打分时,“打分按钮”会变成红色,分数加上用户填写的分数,并显示打分人数、总分数、平均分,。
技术:缓存、中间件、反向解析、重定向。
二、界面
1、投票
image三、代码
1、前端(T)
1.1 base.html
{# 父模板base.html#}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{# 响应式web设计,自适应浏览器大小#}
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="save" content="history">
{% block title %}
<title>首页</title>
{% endblock %}
{% block link %}
{% endblock %}
<link href="{% static 'SitesApp/css/reset.css' %}" rel="stylesheet">
<link href="{% static 'SitesApp/css/sitesAppCss.css' %}" rel="stylesheet">
{# <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">#}
{# <script src="https://cdn.bootcss.com/jquery/1.12.0/jquery.min.js"></script>#}
{# <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>#}
<link href="/static/SitesApp/css/bootstrap.min.css" rel="stylesheet">
{% block style %}
{% endblock %}
<script src="/static/SitesApp/js/jquery.min.js"></script>
<script src="/static/SitesApp/js/bootstrap.min.js"></script>
{% block script %}
<script type="text/javascript"></script>
{% endblock %}
</head>
<body style="background-color: #E6E6FA;">
<a href="{% url 'sitesApp:vote' 1 %}">hhhhh</a>
<div class="box">
<div class="header">
<ul class="nav nav-pills navbar faq-tabbable">
<li role="presentation" class="active"><a href="{% url 'sitesApp:home' %}">首页</a></li>
<li role="presentation"><a href="{% url 'sitesApp:vote' 1 %}">投票</a></li>
<li role="presentation"><a href="{% url 'sitesApp:grade' %}">打分</a></li>
<li role="presentation"><a href="{% url 'sitesApp:review' %}">回顾</a></li>
<li role="presentation"><a href="{% url 'sitesApp:blog' %}">博客</a></li>
<li role="presentation"><a href="{% url 'sitesApp:dataBank' %}">资料</a></li>
<li role="presentation"><a href="{% url 'sitesApp:forum' %}">论坛</a></li>
<li role="presentation"><a href="{% url 'sitesApp:mine' %}">我的</a></li>
<li role="presentation"><a href="{% url 'sitesApp:login' %}">登录</a></li>
<li role="presentation"><a href="{% url 'sitesApp:register' %}">注册</a></li>
</ul>
</div>
<div class="time" >
<span id="mytime"></span>
</div>
<div class="content" style="position: relative;">
{% block content %}
这家伙很懒,还没开始开发...~_~
{% endblock %}
</div>
<div class="footer">
{% block footer %}
开发者 LDC
{% endblock %}
</div>
</div>
<script type="text/javascript">
$(function ($) {
{# 导航栏按钮渲染#}
$(".faq-tabbable").find("li").each(function () {
var a = $(this).find("a:first")[0];
if ($(a).attr("href") === location.pathname) {
$(this).addClass("active");
} else {
$(this).removeClass("active");
}
});
});
{#实时显示时间#}
function showTime(){
nowtime=new Date();
year=nowtime.getFullYear();
month=nowtime.getMonth()+1;
date=nowtime.getDate();
document.getElementById("mytime").innerText=year+"年"+month+"月"+date+" "+nowtime.toLocaleTimeString();
}
<!--定时刷新时间-->
setInterval("showTime()",1000);
</script>
</body>
</html>
1.2 grade.html
{% extends 'SitesApp/base.html' %}
{% block title %}
<title>打分</title>
{% endblock %}
{% block link %}
<link href="https://cdn.bootcss.com/bootstrap-select/1.12.4/css/bootstrap-select.min.css" rel="stylesheet">
<link href="/static/SitesApp/css/bootstrap-select.min.css" rel="stylesheet">
{% endblock %}
{% block content %}
<div style="width: 400px;margin: 0 auto;">
<img style="margin: 0 0 5px; height: 100px;display: inline-block;" src="/static/SitesApp/imgs/think.jpg" title="思考">
<div class="form-group">
<span class="glyphicon glyphicon-user"></span>
<strong style="color: #222;font-size: 16px;">分享者:</strong>
{% if who %}
<input list="browsers" id="whoId" class="selectpicker show-tick" value="{{ who.cName }}" onchange="inputSelect()">
{% else %}
<input list="browsers" id="whoId" class="selectpicker show-tick" placeholder="请选择一位分享者" onchange="inputSelect()">
{% endif %}
<datalist id="browsers">
{% for c in candidates %}
<option value="{{ c.cName }}" data-value="{{ c.cName }}" data-id="{{ c.id }}">{{ c.id }}</option>
{% endfor %}
</datalist>
{% ifequal ip '127.0.0.1' %}
<a href="{% url 'sitesApp:addCandidate' %}" style="color: green;">新增分享者</a>
{% endifequal %}
</div>
</div>
<div style="width: 400px;margin: 0 auto;">
<table>
<thead>
<tr>
<th style="font-size: 16px;width: 100px;text-align: center">当前总分数</th>
<th style="font-size: 16px;width: 100px;text-align: center">班级总人数</th>
<th style="font-size: 16px;width: 100px;text-align: center">打分人数</th>
<th style="font-size: 16px;width: 100px;text-align: center">平均分</th>
</tr>
</thead>
<tbody>
<tr>
{% if grade %}
<td>{% widthratio grade.num 1 grade.avg %}</td>
<td>60</td>
<td>{{ grade.num }}</td>
<td>{{ grade.avg }}</td>
{% else %}
<td>0</td>
<td>60</td>
<td>0</td>
<td>0</td>
{% endif %}
</tr>
</tbody>
</table>
</div>
{% csrf_token %}
<button class="vote" style="margin: 10px 10px 0" value="{{ who.id }}" name="{{ who.cName }}" title ="{{ who.cDeclaration }}"><span style="color: #D2691E;">打分</span></button>
<button class="chat" value="{{ who.id }}" name="{{ who.cName }}" title ="{{ who.cDeclaration }}"><span style="color: #D2691E;">留言</span></button>
<button class="reload" style="margin: 10px 10px 0" title ="{{ who.cDeclaration }}"><span style="color: #D2691E;">刷新</span></button>
<div style="margin: 0 auto;width: 1200px;">
<div style="height: 280px;width:400px;text-align: center;float: left">
<h2 style="height: 20px; width: 150px;margin-bottom: 15px;">打分区</h2>
<div id="chat" style="height: 200px; overflow: auto;width: 350px;border: 2px solid black;border-radius: 5px;">
<table >
<thead>
<tr class="danger">
<th style="width: 30px;text-align: center;">序号</th>
<th style="width: 80px;text-align: center;">时间</th>
<th style="width: 50px;text-align: center;">打分者</th>
<th style="width: 40px;text-align: center;">分数</th>
</tr>
</thead>
<tbody >
{% if voteRecords %}
{% for voteRecord in voteRecords %}
<tr class="{% cycle 'active' 'success' 'warning' 'info' %}">
<td> {{ forloop.counter }} </td>
<td >{{ voteRecord.vDate|date:'Y-m-d ' }}</td>
<td style=" padding: 0 20px;">guest{{ forloop.counter }} </td>
<td style=" padding: 0 20px;">{{ voteRecord.vPolls }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4">无数据</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
<div style="height: 280px;width:600px;margin: 0 0 0 40px;text-align: center;float: left;">
<h2 style="height: 20px; width: 100px;margin-bottom: 15px;">留言区</h2>
<div id="chat" style="height: 200px; width: 800px;overflow: auto;border: 2px solid black;border-radius: 5px;">
<table >
<thead>
<tr class="danger">
<th style="width: 40px;text-align: center;">序号</th>
<th style="width: 80px;text-align: center;">留言时间</th>
<th style="width: 60px;text-align: center;">留言者</th>
<th style="width: 80px;text-align: center;">标题</th>
<th style="width: 550px;text-align: center;">内容</th>
</tr>
</thead>
<tbody >
{% if messages %}
{% for message in messages %}
<tr class="{% cycle 'active' 'success' 'warning' 'info' %}">
<td> {{ forloop.counter }} </td>
<td >{{ message.crDateTime|date:'H:i:s' }}</td>
<td style=" padding: 0 40px;">guest{{ forloop.counter }} </td>
<td style=" padding: 0 20px;">评价</td>
<td style=" padding: 0 20px;">{{ message.crInfo }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4">无数据</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
{% endblock %}
{% block script %}
<script src="https://cdn.bootcss.com/bootstrap-select/1.12.4/js/bootstrap-select.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap-select/1.12.4/js/i18n/defaults-zh_CN.min.js"></script>
<script src="/static/SitesApp/js/bootstrap-select.min.js"></script>
<script src="/static/SitesApp/js/defaults-zh_CN.min.js"></script>
<script type="text/javascript">
jQuery(function ($) {
$('#whoId').focus();
{#如果用户已经打分就把打分按钮显示红色#}
{% ifequal done 1 %}
$('.vote').css('background-color','red').find('span').css('color','#080808');
{% endifequal %}
var whoId = 0;
var times = {{ times }};
$("button").click(function () {
whoId = checkInput();
if(whoId === 0){
return
}
{# alert(whoId);#}
var btnThis = $(this);
var btnType = $(this).attr("class");
var name = $(this).attr("name");
<!--打分-->
if(btnType == 'vote'){
var judge1 = prompt("请给"+name+"打分(0-100分)");
grades = parseInt(judge1);
if( !checkNumber(judge1) || grades < 0 || grades > 100){
alert("分数范围为0-100");
}
else {
var url = '{% url "sitesApp:addGrade" %}';
$.ajax({
type:"POST",
url: url,
data:{'whoId':whoId,'times': times,'grades':grades},
dataType: "json",
success: function (res) {
{#alert(res);#}
if (res['status'] == 1) {
alert("打分成功!");
{#把打分按钮显示红色#}
btnThis.css('background-color','red').find('span').css('color', '#080808');
} else {
alert("您今天已经对" + name + " 打过分了!");
}
url = "/app/grade/?whoId="+whoId+"×="+times;
window.location.href = url;
},error: function (e) {
alert(e.responseText);
}
});
}
}else if(btnType == 'chat'){
var judge = prompt(name + "留言区(最多40个字)");
if (judge && judge.length <= 40) {
url = '{% url "sitesApp:chat" %}';
$.ajax({
type:"POST",
url:url,
data:{"cInfo":judge, "whoId":whoId},
dataType:"json",
success: function(res) {
if(res['status'] == 1){
url = "/app/grade/?whoId="+whoId+"×="+times;
window.location.href = url;
}
}
});
} else {
alert("留言失败");
}
}else if(btnType == 'reload'){
url = "/app/grade/?whoId="+whoId+"×="+times;
window.location.href = url;
}else{
}
});
});
function inputSelect(){
var whoId = checkInput();
var times = {{ times }};
var url = "/app/grade/?whoId="+whoId+"×="+times;
window.location.href = url;
}
function checkInput() {
var input_select=$("#whoId").val();
var option = $('option');
var option_length=option.length;
var option_id='';
for(var i=0;i<option_length;i++){
var option_value=option.eq(i).attr('data-value');
if(input_select==option_value){
option_id=$("option").eq(i).attr('data-id');
break;
}
}
if(option_id != 0){
return option_id;
}else {
alert("请选择一位分享者!!");
return 0;
}
}
//验证字符串是否是数字
function checkNumber(theObj) {
var reg = /^[0-9]+.?[0-9]*$/;
return reg.test(theObj);
}
function showTime(){
nowtime=new Date();
year=nowtime.getFullYear();
month=nowtime.getMonth()+1;
date=nowtime.getDate();
document.getElementById("mytime").innerText=year+"年"+month+"月"+date+" "+nowtime.toLocaleTimeString();
}
<!--定时刷新时间-->
setInterval("showTime()",1000);
</script>
{% endblock %}
2 路由处理(V)
2.1 项目下的总路由
urlpatterns = [
url('^app/',include('SitesApp.urls',namespace='sitesApp'))
]
2.2 子应用下的路由
# 打分旧地址
url(r'^shareNav/', views.shareNav,name='shareNav'),
# 打分首页
url(r'^grade/', views.grade,name='grade'),
# 增加分数
url(r'^addGrade/', views.addGrade,name='addGrade'),
3、视图函数处理(Views)
3.1 打分主页
# 打分
@csrf_exempt
def grade(request):
print('来到了这里')
vtype = opeVoteTypeT.query(vType__contains='打分').first()
candidates = Candidate.cManager.filter(cVoteType_id=vtype.id).order_by('cPinyin')
dictData = {'candidates':candidates}
ip = getUserIP(request)
whoId = request.GET.get('whoId', None)
times = request.GET.get('times', None)
print('要谁的数据',whoId)
if whoId and whoId != '0':
# 判断用户是否已经打分,
isVote = opeVoteRecordT.query(vTimes=times, vCandidateId_id=whoId, vComIP=ip,
vDate=datetime.datetime.now().__format__('%Y-%m-%d')).first()
if isVote:
# 用户已经打分,打分按钮就显示红色
dictData['done'] = 1
candidate = candidates.get(id=whoId)
dictData['who'] = candidate
print('候选者的名字',candidate.cName)
# 获取打分记录
voteRecords = opeVoteRecordT.query(vCandidateId_id=whoId,vTimes=times,vDate=datetime.datetime.now().__format__('%Y-%m-%d'))
if voteRecords.exists():
dictData['voteRecords'] = voteRecords
# 统计分数
dictData['grade'] = voteCount(voteRecords)
for k, v in dictData['grade'].items():
print(k, v)
# 获取留言信息
now = datetime.datetime.now()
start = now - datetime.timedelta(hours=23, minutes=59, seconds=59)
chatRecords = ChatRecord.crManager.filter(crTopic=whoId,crDateTime__gt=start,crType=candidate.cVoteType_id)
if chatRecords.exists():
dictData['messages'] = chatRecords
if ip == '127.0.0.1':
dictData['ip'] = ip
dictData['times'] = 1
return render(request, 'SitesApp/grade.html',context=dictData)
3.2 增加分数
# 增加分数
@csrf_exempt
def addGrade(request):
print('***********************************')
whoId = request.POST.get('whoId', None)
times = request.POST.get('times', None)
grades = request.POST.get('grades', None)
data = {'status': 0, 'msg': 'no whoId'}
if not whoId:
return JsonResponse(data)
# 获取候选者信息
candidate = Candidate.cManager.get(id=whoId)
# 获取用户IP
ip = getUserIP(request)
user = getUser(request)
# 判断用户是否已经打分,
isVote = opeVoteRecordT.query(vTimes=times, vCandidateId_id=whoId, vComIP=ip,
vDate=datetime.datetime.now().__format__('%Y-%m-%d')).first()
if isVote:
print('已经投过票了')
return JsonResponse({'status': 0, 'msg': 'already grade'})
# 若用户还没有打分就添加打分记录
if not opeVoteRecordT.add(vUserId_id=user.id, vCandidateId_id=candidate.id, vComIP=ip,
vTypeId_id=candidate.cVoteType_id, vPolls=grades, vTimes=times):
print('新增打分记录出错')
return JsonResponse({'status': 0, 'msg': 'add voteRecord faild'})
#候选者打分人数加1
if not opeCandidateT.modify(candidate.id, cVotes=candidate.cVotes + 1):
print('修改候选者记录出错')
return JsonResponse({'status': 0, 'msg': 'modify candidateRecord faild'})
print('给谁打分', whoId, '第几轮', times, '多少分:', grades)
print('运行到这里啦')
data = {'status': 1, 'msg': 'success'}
print(type(data),'***',data)
return JsonResponse(data)
3.3 留言
# 留言
@csrf_exempt
def chat(request):
cInfo = request.POST.get('cInfo')
whoId = request.POST.get('whoId')
print('给谁留言',whoId)
# 通过用户IP查找用户的名字
ip = getUserIP(request)
user = getUser(request)
# 查找候选者
candidate = Candidate.cManager.get(pk=whoId, isDelete=0)
if opeChatRecordT.add(crUserId_id=user.id,crNickName = user.uNickName,crIP = ip,crInfo = cInfo,crTopic = candidate.id,crType = candidate.cVoteType_id):
return JsonResponse({'status': 1, 'msg': 'success'})
return JsonResponse({'status': 0, 'msg': 'faild'})
3.4 业务逻辑
1、用户第一次访问打分主页时,从服务器获取候选者信息加载到下拉框中。
2、用户选择候选者后,从服务器获取当天的分数和留言信息加载到打分区和留言区。
3、点击打分按钮时,把候选者id和分数传给服务器,服务器增加打分记录,修改分数,把处理结果返回给客户端。
4、如果用户已经打过分,打分按钮显示红色,再点击时提示已经打过分。
5、留言内容限定为40字。
6、判断当前ip是否为127.0.0.1,如果是就显示“新增候选者”按钮,可以通过此按钮添加候选者,其它ip则不行。
7、如果当前ip在用户表中找不到,就把当前Ip在后台自动添加到用户表。