Django项目-个人网站之投票模块
Django项目之个人网站
关注公众号“轻松学编程”了解更多。
Github地址:https://github.com/liangdongchang/MyWeb.git
感兴趣的可以fork或star一下
功能模块二:投票
一、说明
功能:用户对喜欢的编程语言进行投票、留言。
用户点击投票时“投票按钮”会变成红色,票数加1,再次点击时会取消投票操作,按钮变成绿色,票数减1(相当于没有投票)。
技术:缓存、分页、反向解析、重定向。
二、界面
1、投票
三、代码
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 vote.html
{% extends 'SitesApp/base.html' %}
{% block title %}
<title>投票</title>
{% endblock %}
{% block content %}
{% ifequal ip '127.0.0.1' %}
<a href="{% url 'sitesApp:addCandidate' %}" style="color: green;margin: 0 0 10px;display: inline-block">新增候选者</a>
{% endifequal %}
<div style="width: 800px;margin: 0 auto;">
{% for condidate in page.object_list %}
<div style="display: inline-block;position: relative;">
<span style="color: red;">{{ condidate.cName }}</span>
<img src="/static/SitesApp/imgs/language/{{ condidate.cIcon }}" style="height: 60px;margin: 0 10px 10px;display: block;" title="{{ condidate.cDeclaration }}">
<button class="vote" condidateId="{{ condidate.id }}" name="{{ condidate.cName }}" voteCid="{{ condidate.id }}" style="background-color: #95D195;" title="投票"><span class=" glyphicon glyphicon-thumbs-up " ></span></button>
<button class="chat" chatCid="{{ condidate.id }}" title="留言"><span class="glyphicon glyphicon-envelope" title="留言"></span></button>
<br>
票数:<span id="{{ condidate.id }}" class="badge">{{ condidate.cVotes }}</span>
</div>
{% endfor %}
<br>
{# 分页器:html内容拷贝于bootstrap网站-组件-分页#}
{# bootstrap是一整套成熟经典的页面组件框架#}
<nav aria-label="Page navigation">
<ul class="pagination">
{# 上一页按钮#}
{# 如果有上一页#}
{% if page.has_previous %}
<li>
{# 点击超链接,对上一页的页面发起访问#}
<a href="{% url 'sitesApp:vote' page.previous_page_number %}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{# 如果没有上一页#}
{% else %}
{# 当没有上一页时,阅读bootrap文档得知,对当前li使用disabled样式#}
<li class="disabled">
{# href="#",处于禁用状态的按钮被点击时直接跳转本页#}
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{# 页码按钮#}
{# 遍历传入的页码范围#}
{% for p in pagerange %}
{# 如果页码=当前页页码#}
{% ifequal p currentpage %}
{# 被选中的页码具有高亮效果,阅读bootrap文档得知,对当前li使用active样式#}
{# {% url 'sitesApp:vote' p %} 点击页码,对第p页的路由发起访问#}
<li class="active"><a href="{% url 'sitesApp:vote' p %}">{{ p }}</a></li>
{% else %}
{# 非当前页页码普通显示#}
<li><a href="{% url 'sitesApp:vote' p %}">{{ p }}</a></li>
{% endifequal %}
{% endfor %}
{# 下一页按钮#}
{% if page.has_next %}
<li>
{# 点击超链接,对下一页的页面发起访问#}
<a href="{% url 'sitesApp:vote' page.next_page_number %}" aria-label="Next">
<span aria-hidden="true">»</span>
</a></li>
{% else %}
{# 当没有下一页时,阅读bootrap文档得知,对当前li使用disabled样式#}
<li class="disabled">
{# href="#",处于禁用状态的按钮被点击时直接跳转本页#}
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
<div style="height: 280px;width:800px;margin: 0 auto;">
<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 style="width: 150px;">{{ message.crDateTime|date:'Y-m-d H:i' }}</td>
<td style=" padding: 0 20px;">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 type="text/javascript">
/*
$(this)当前被点击的元素
<a style='color:black;'>你好</a>
element.css('color','red')设置元素的CSS样式
element.css('color')获取元素的CSS样式
<a href='xxx'>你好</a>
element.attr('href','http://www.baidu.com')设置元素的html属性
element.attr('href')获取元素的html
<a href='xxx'>你好</a>
element.html('我好')设置元素的html节点内容
element.html()获取元素的html节点内容
*/
$(function($){
<!--如果用户已经投过票,投票按钮就显示红色-->
var isVoteLists = {{ isVoteLists }}
{# console.log(isVoteLists);#}
{#如果用户已经点击了就显示红色#}
$('*[voteCid]').each(function () {
var voteCid = $(this);
if( $.inArray(parseInt(voteCid.attr('voteCid')), isVoteLists) >= 0){
voteCid.css("background", "#D1191B");
}
});
$('.vote').click(function () {
var voteBtn = $(this);
var cid = voteBtn.attr('voteCid');
var spanGnum = voteBtn.next().next().next();
$.getJSON(
"{% url 'sitesApp:addVote' %}",
{"cid": cid},
function (data) {
console.log(data);
{# 投票成功#}
if(data['status'] == 1){
voteBtn.css("background", "#D1191B");
}else if(data['status'] == 2){
{#用户再次点击就显示绿色#}
voteBtn.css("background", "#95D195");
}
spanGnum.html(data['poills'] );
window.location.href = '{% url "sitesApp:vote" %}';
}
)
});
$('.chat').click(function () {
var voteBtn = $(this);
var whoId = voteBtn.attr('chatCid');
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){
window.location.href = '{% url "sitesApp:vote" %}';
}
}
});
} else {
alert("留言失败");
}
});
});
</script>
{% endblock %}
2 路由处理(V)
2.1 项目下的总路由
urlpatterns = [
url('^app/',include('SitesApp.urls',namespace='sitesApp'))
]
2.2 子应用下的路由
# 投票
url(r'^vote/(?P<pageNum>\d+)?', views.vote,name='vote'),
# 增加投票
url(r'^addVote/', views.addVote, name='addVote'),
3、视图函数处理(Views)
3.1 投票主页
# 投票
def vote(request,pageNum):
print('要第几页数据',pageNum)
if not pageNum:
pageNum = 1
# 获取用户IP
ip = getUserIP(request)
# 把本机地址传到页面,页面才能显示新增候选者按钮
dictData = {'ip': '127.0.0.1'}
# 获取候选者
candidates = Candidate.cManager.filter(cVoteType__vType__contains='编程').order_by('-cVotes')
# 用户投票结果列表
isVoteLists = []
for candidate in candidates:
print(candidate.cName,'的票数为',candidate.cVotes)
# 判断当前IP今天是否已经对该候选者投过票
isVote = opeVoteRecordT.query(vCandidateId_id=candidate.id,isDelete=0,vTypeId_id=candidate.cVoteType_id, vComIP=ip,
vDate=datetime.datetime.now().__format__('%Y-%m-%d'))
if isVote.exists():
isVoteLists.append(candidate.id)
dictData['isVoteLists'] = isVoteLists
# 获取留言信息
chatRecords = ChatRecord.crManager.filter(crType=candidates.first().cVoteType_id)
if chatRecords.exists():
dictData['messages'] = chatRecords
# 构建分页器对象,candidates=候选者列表,5=每页显示的个数
paginator = Paginator(candidates, 5)
# 获取第n页的页面对象
page = paginator.page(pageNum)
# Paginator和Page的常用API
# page.previous_page_number()
# page.next_page_number()
# page.has_previous()
# page.has_next()
# 构造页面渲染的数据
'''
渲染需要的数据:
- 当前页的候选者对象列表
- 分页页码范围
- 当前页的页码
'''
if request.method == 'GET':
# 当前页的候选者对象列表
dictData['page'] = page
# 分页页码范围
dictData['pagerange'] = paginator.page_range
# 当前页的页码
dictData['currentpage'] = page.number
return render(request, 'SitesApp/vote.html', context=dictData)
3.2 增加票数
# 增加投票数
def addVote(request):
cid = request.GET.get('cid',None)
if not cid:
return JsonResponse({'status':0,'msg':'no cid'})
# 获取候选者信息
candidate = Candidate.cManager.get(pk=cid)
poills = candidate.cVotes
ip = getUserIP(request)
data = {'status': 0,'msg':'vote failed'}
# 判断当前IP今天是否已经对该候选者投过票
isVote = opeVoteRecordT.query(vCandidateId_id=cid,vTypeId__vType__contains='编程',vComIP=ip,vDate=datetime.datetime.now().__format__('%Y-%m-%d')).first()
# isDelete初始值为0,表示记录没有被逻辑删除,用户再次点击投票就把记录删除,isDelete置为1
if isVote:
data['status'] = 2
data['msg'] = 'already voted'
# isDelete为True表示取消投票
if isVote.isDelete:
poills += 1
else:
poills -= 1
# 修改投票记录
if not opeVoteRecordT.modify(isVote.id,isDelete= not isVote.isDelete):
print('修改投票记录失败')
return JsonResponse(data)
print('现在是取消(True)还是投票(False)',isVote.isDelete)
# 修改候选者票数
if not opeCandidateT.modify(candidate.id,cVotes=poills):
print('修改候选者记录失败')
return JsonResponse(data)
else:
user=getUser(request)
if not user:
return JsonResponse(data)
# 增加投票记录
if not opeVoteRecordT.add(vUserId_id=user.id,vCandidateId_id=candidate.id,vComIP=ip,vTypeId_id=candidate.cVoteType_id,vPolls=1,vTimes=1):
return JsonResponse(data)
# 修改候选者票数
if not opeCandidateT.modify(candidate.id,cVotes=candidate.cVotes+1):
return JsonResponse(data)
data['status'] = 1
data['msg'] = 'success'
data['poills'] = poills
return JsonResponse(data)
######3.3 业务逻辑
1、用户第一次访问投票主页时,从服务器获取候选者信息,显示候选者图片和票数。
2、用户选择候选者后,从服务器获取票数和留言信息加载到票数取和留言区。
3、点击投票按钮时,把候选者id传给服务器,服务器增加投票记录,修改票数,把处理结果返回给客户端。投票按钮显示红色,显示最新票数。
4、如果用户再次点击投票按钮,服务器则把该候选者的票数减1,把投票记录设置为逻辑删除isDelete=1.投票按钮显示绿色。
5、留言内容限定为40字。
6、判断当前ip是否为127.0.0.1,如果是就显示“新增候选者”按钮,可以通过此按钮添加候选者,其它ip则不行。
7、如果当前ip在用户表中找不到,就把当前Ip在后台自动添加到用户表。
后记
【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。
也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!
公众号
关注我,我们一起成长~~
Django项目-个人网站之投票模块的更多相关文章
- Django项目-个人网站之事项模块
Django项目之个人网站 关注公众号"轻松学编程"了解更多. Github地址:https://github.com/liangdongchang/MyWeb.git 感兴趣的可 ...
- Django项目: 3.用户注册功能
本章内容的补充知识点 导入库的良好顺序: 1.系统库 2.django库 3.自己定义的库(第三方库) redis缓存数据库的数据调用速度快,但是不利于长时间保存. mysql用于长时间存储,但是调用 ...
- 在nginx上部署django项目--------Gunicorn+Django+nginx+mysql
一.安装nginx 以前的博客我有写,这里就不写了 http://www.cnblogs.com/wt11/p/6420442.html 二.安装mysql 我用的mysql5.7 64位的二进制包 ...
- Django项目实践4 - Django网站管理(后台管理员)
http://blog.csdn.net/pipisorry/article/details/45079751 上篇:Django项目实践3 - Django模型 Introduction 对于某一类 ...
- Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 ...
- 零基础入门Python实战:四周实现爬虫网站 Django项目视频教程
点击了解更多Python课程>>> 零基础入门Python实战:四周实现爬虫网站 Django项目视频教程 适用人群: 即将毕业的大学生,工资低工作重的白领,渴望崭露头角的职场新人, ...
- Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基础文件配置,Web框架的本质,服务器程序和应用程序(wsgiref服务端模块,jinja2模板渲染模块)的使用
Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基 ...
- Django项目中模板标签及模板的继承与引用【网站中快速布置广告】
Django项目中模板标签及模板的继承与引用 常见模板标签 {% static %} {% for x in range(x) %}{% endfor %} 循环的序号{% forloop %} 循环 ...
- Django项目打分系统
Django项目之个人网站 关注公众号"轻松学编程"了解更多. Github地址:https://github.com/liangdongchang/MyWeb.git 感兴趣的可 ...
随机推荐
- C 面向对象编程 --- 一模块的串口协议解析
// 任务目的// 解析串口收到的54个字节.这54个字节包含了8个车道的5大信息以及校验信息.// 实现了查询每条车道包含了哪些信息. #include <stdio.h>#includ ...
- Tomcat 第六篇:类加载机制
1. 引言 Tomcat 在部署 Web 应用的时候,是将应用放在 webapps 文件夹目录下,而 webapps 对应到 Tomcat 中是容器 Host ,里面的文件夹则是对应到 Context ...
- javaagent+asm破解censum
内容介绍 最近在学习字节码相关知识,了解到通过ASM字节码改写技术来做破解一些软件破解,非常感兴趣,本文记录一下破解 Censum的过程(仅个人学习使用). 之前也写过一篇暴力破解Censum的文章, ...
- IPA的动态库注入+企业重签名过程
[摘录]之前在进行iOS测试过程中由于要获取一定数据信息,因此需要对原本的安装包进行代码注入并且重新打包安装,因此就需要使用重签名策略,在此进行分享,希望大家可以使用其中的方法来运用到自身的项目中. ...
- Python操作图像
安装Pillow pip install Pillow 打开图像 from PIL import Image img = Image.open("./lena.tiff") 保存图 ...
- MeteoInfoLab脚本示例:线性拟合
MeteoInfoLab提供一个线性拟合函数linregress,参数是参与拟合的两个数据序列,返回拟合的斜率.截距和相关系数.有了上述拟合参数可以用polyval函数生成拟合数据(直线).然后可以将 ...
- linux(centos8):安装kubernetes worker节点并加入到kubernetes集群(kubernetes 1.18.3)
一,安装kubernetes前的准备工作 安装前的准备工作(master\worker都要进行) 参见: https://www.cnblogs.com/architectfore ...
- nginx安全:配置网站图片防盗链
一,为什么要做防盗链? 1,什么是盗链? 比如某人有一个A网站, 他不愿自己存储图片,(因为磁盘和带宽都有成本) 就在自己A网站的页面上直接插入B网站的图片, 从而为自己吸引流量,这就是盗链 2,为什 ...
- Python之tuple元组详解
元组:有序,一级元素不可以修改.不能被增加或删除(元组是可迭代对象) 一般写法括号内最后面加个英文逗号用来区分: test = (,) test1 = (11,22,) 例: test = (12 ...
- Java9系列第8篇-Module模块化编程
我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...