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">&laquo;</span>
</a>
</li> {# 如果没有上一页#}
{% else %}
{# 当没有上一页时,阅读bootrap文档得知,对当前li使用disabled样式#}
<li class="disabled">
{# href="#",处于禁用状态的按钮被点击时直接跳转本页#}
<a href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</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">&raquo;</span>
</a></li>
{% else %}
{# 当没有下一页时,阅读bootrap文档得知,对当前li使用disabled样式#}
<li class="disabled">
{# href="#",处于禁用状态的按钮被点击时直接跳转本页#}
<a href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</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项目-个人网站之投票模块的更多相关文章

  1. Django项目-个人网站之事项模块

    Django项目之个人网站 关注公众号"轻松学编程"了解更多. Github地址:https://github.com/liangdongchang/MyWeb.git 感兴趣的可 ...

  2. Django项目: 3.用户注册功能

    本章内容的补充知识点 导入库的良好顺序: 1.系统库 2.django库 3.自己定义的库(第三方库) redis缓存数据库的数据调用速度快,但是不利于长时间保存. mysql用于长时间存储,但是调用 ...

  3. 在nginx上部署django项目--------Gunicorn+Django+nginx+mysql

    一.安装nginx 以前的博客我有写,这里就不写了 http://www.cnblogs.com/wt11/p/6420442.html 二.安装mysql 我用的mysql5.7  64位的二进制包 ...

  4. Django项目实践4 - Django网站管理(后台管理员)

    http://blog.csdn.net/pipisorry/article/details/45079751 上篇:Django项目实践3 - Django模型 Introduction 对于某一类 ...

  5. Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块

    Python第十三天   django 1.6   导入模板   定义数据模型   访问数据库   GET和POST方法    SimpleCMDB项目   urllib模块   urllib2模块 ...

  6. 零基础入门Python实战:四周实现爬虫网站 Django项目视频教程

    点击了解更多Python课程>>> 零基础入门Python实战:四周实现爬虫网站 Django项目视频教程 适用人群: 即将毕业的大学生,工资低工作重的白领,渴望崭露头角的职场新人, ...

  7. Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基础文件配置,Web框架的本质,服务器程序和应用程序(wsgiref服务端模块,jinja2模板渲染模块)的使用

    Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基 ...

  8. Django项目中模板标签及模板的继承与引用【网站中快速布置广告】

    Django项目中模板标签及模板的继承与引用 常见模板标签 {% static %} {% for x in range(x) %}{% endfor %} 循环的序号{% forloop %} 循环 ...

  9. Django项目打分系统

    Django项目之个人网站 关注公众号"轻松学编程"了解更多. Github地址:https://github.com/liangdongchang/MyWeb.git 感兴趣的可 ...

随机推荐

  1. modelviewset views

    Python 1.4创建user/serializers.py写序列化器 from rest_ framework import serializers from user .models impor ...

  2. python对文件操作 r w a 文件复制/修改

    文件操作简介: 使用python来读写文件是非常简单的操作.我们使用 open() 函数来打开一个文件,获取到文件句柄.然后 通过文件句柄就可以进行各种各样的操作了.根据打开⽅方式的不同能够执行的操作 ...

  3. 《To B产品经理进阶》

    一.沙漏哟:To B产品技术标准化(全网独家) 经济机器是怎样运行的(超级简单模式理解经济运行规律) <俞军产品方法论>(思维模型.交易模型.经济学.心理学) <深度思考六步法> ...

  4. Flink深入浅出: 应用部署与原理图解(v1.11)

    往期推荐: Flink深入浅出:内存模型 Flink深入浅出:JDBC Source从理论到实战 Flink深入浅出:Sql Gateway源码分析 Flink深入浅出:JDBC Connector源 ...

  5. Selenium截屏 图片未加载的问题解决--【懒加载】

    需求: 截屏后转PDF. 问题: selenium截屏后,图片未加载 如下图: 原因: 网站使用了懒加载技术:只有在浏览器中纵向滚动条滚动到指定的位置时,页面的元素才会被动态加载. 什么是图片懒加载? ...

  6. Java中类型判断的几种方式

    1. 前言 在Java这种强类型语言中类型转换.类型判断是经常遇到的.今天就细数一下Java中类型判断的方法方式. 2. instanceof instanceof是Java的一个运算符,用来判断一个 ...

  7. 【Zabbix】在CentOS 7上搭建Zabbix服务,收集Windows客户端计数器性能数据(含过程中遇到的问题解决方法)

    1.环境 1.1.关闭防火墙 命令:systemctl stop firewalld 或者 systemctl stop firewalld.service (备注:相应的,若要开启防火墙,将对应的& ...

  8. Python数据类型--元组(tuple)

    元组与列表非常相似,最大区别在于: (1)元组是不可修改的,定义之后就"固定"了. (2)元组在形式上是用()这样的圆括号括起来 (3)元组不能插入或删除元素 注:元素可修改与不可 ...

  9. bootStrap小结2

    <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...

  10. 【纯水题】CF 833A The Meaningless Game

    题目大意 洛谷链接 现在两个人做游戏,每个人刚开始都是数字\(1\),谁赢了就能乘以\(k^2\),输的乘以\(k\),现在给你最终这两个人的得分,让你判断是否有这个可能,有可能的话输出Yes,否则输 ...