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. Electron安装过程深入解析(读完此文解决Electron应用无法启动,无法打包的问题)

    1. 安装Electron依赖包 开发者往往通过npm install(或 yarn add)指令完成为Node.js工程安装依赖包的工作, 安装Electron也不例外,下面是npm和yarn的安装 ...

  2. 机器学习可解释性系列 - 是什么&为什么&怎么做

    机器学习可解释性分析 可解释性通常是指使用人类可以理解的方式,基于当前的业务,针对模型的结果进行总结分析: 一般来说,计算机通常无法解释它自身的预测结果,此时就需要一定的人工参与来完成可解释性工作: ...

  3. jwtUtils顾名思意

    1 package com.pipihao.blog.util; 2 import java.util.Date; 3 4 import javax.crypto.SecretKey; 5 impor ...

  4. 001 win10下安装linux子系统--Ubuntu及其图形界面

    首次启动图形界面关键步骤及相关命令: 步骤: 打开Xlunch 打开XLaunch,选择:"one large window",Display number设置成0,其它默认即可, ...

  5. 【题解】 [EZEC-4]求和

    对于百分之十的数据:随便过. 下面推式子: \[\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j)^{i+j} \] \[=\sum_{d=1}^n\sum_{i=1}^n\sum_{ ...

  6. ansible-命令使用说明

    1. ansible命令的使用说明 ansible 主机或组-m 模块名-a '模块参数' ansible参数 表示调用什么模块,使用模块的那些参数 • 主机和组,是在/etc/ansible/hos ...

  7. Vue 全宇宙最浪 VSCode 配置、插件

    别人的那一堆配置.插件我就不写了- 首先进入官网下载并安装. 基本配置 在编译器 文件 >> 首选项 >> 设置,可以拷贝相面的选项后搜索相关配置 设置制表符等于空格数为 2: ...

  8. 树状数组(BIT)—— 一篇就够了

    树状数组(BIT)-- 一篇就够了 前言.内容梗概 本文旨在讲解: 树状数组的原理(起源,原理,模板代码与需要注意的一些知识点) 树状数组的优势,缺点,与比较(eg:线段树) 树状数组的经典例题及其技 ...

  9. go 结构体与方法

    go 结构体与方法   go 结构体相当于 python 中类的概念,结构体用来定义复杂的数据结构,存储很多相同的字段属性 结构体的定义 1.结构体的定义以及简单实用 package main imp ...

  10. centos8平台使用loginctl管理登录用户与session

    一,loginctl的用途: 控制 systemd 登录管理器 管理当前登录的用户和session 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/a ...