Django项目之个人网站

关注公众号“轻松学编程”了解更多。
Github地址:https://github.com/liangdongchang/MyWeb.git

感兴趣的可以fork或star一下

功能模块二:投票

一、说明

功能:用户对喜欢的编程语言进行投票、留言。

用户点击投票时“投票按钮”会变成红色,票数加1,再次点击时会取消投票操作,按钮变成绿色,票数减1(相当于没有投票)。

技术:缓存、分页、反向解析、重定向。

二、界面
1、投票

三、代码
1、前端(T)
1.1 base.html
  1. {# 父模板base.html#}
  2. {% load static %}
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. {# 响应式web设计,自适应浏览器大小#}
  8. <meta name="viewport" content="width=device-width, initial-scale=1">
  9. <meta name="save" content="history">
  10. {% block title %}
  11. <title>首页</title>
  12. {% endblock %}
  13. {% block link %}
  14. {% endblock %}
  15. <link href="{% static 'SitesApp/css/reset.css' %}" rel="stylesheet">
  16. <link href="{% static 'SitesApp/css/sitesAppCss.css' %}" rel="stylesheet">
  17. {# <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">#}
  18. {# <script src="https://cdn.bootcss.com/jquery/1.12.0/jquery.min.js"></script>#}
  19. {# <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>#}
  20. <link href="/static/SitesApp/css/bootstrap.min.css" rel="stylesheet">
  21. {% block style %}
  22. {% endblock %}
  23. <script src="/static/SitesApp/js/jquery.min.js"></script>
  24. <script src="/static/SitesApp/js/bootstrap.min.js"></script>
  25. {% block script %}
  26. <script type="text/javascript"></script>
  27. {% endblock %}
  28. </head>
  29. <body style="background-color: #E6E6FA;">
  30. <a href="{% url 'sitesApp:vote' 1 %}">hhhhh</a>
  31. <div class="box">
  32. <div class="header">
  33. <ul class="nav nav-pills navbar faq-tabbable">
  34. <li role="presentation" class="active"><a href="{% url 'sitesApp:home' %}">首页</a></li>
  35. <li role="presentation"><a href="{% url 'sitesApp:vote' 1 %}">投票</a></li>
  36. <li role="presentation"><a href="{% url 'sitesApp:grade' %}">打分</a></li>
  37. <li role="presentation"><a href="{% url 'sitesApp:review' %}">回顾</a></li>
  38. <li role="presentation"><a href="{% url 'sitesApp:blog' %}">博客</a></li>
  39. <li role="presentation"><a href="{% url 'sitesApp:dataBank' %}">资料</a></li>
  40. <li role="presentation"><a href="{% url 'sitesApp:forum' %}">论坛</a></li>
  41. <li role="presentation"><a href="{% url 'sitesApp:mine' %}">我的</a></li>
  42. <li role="presentation"><a href="{% url 'sitesApp:login' %}">登录</a></li>
  43. <li role="presentation"><a href="{% url 'sitesApp:register' %}">注册</a></li>
  44. </ul>
  45. </div>
  46. <div class="time" >
  47. <span id="mytime"></span>
  48. </div>
  49. <div class="content" style="position: relative;">
  50. {% block content %}
  51. 这家伙很懒,还没开始开发...~_~
  52. {% endblock %}
  53. </div>
  54. <div class="footer">
  55. {% block footer %}
  56. 开发者 LDC
  57. {% endblock %}
  58. </div>
  59. </div>
  60. <script type="text/javascript">
  61. $(function ($) {
  62. {# 导航栏按钮渲染#}
  63.   $(".faq-tabbable").find("li").each(function () {
  64.     var a = $(this).find("a:first")[0];
  65.      if ($(a).attr("href") === location.pathname) {
  66.       $(this).addClass("active");
  67.     } else {
  68.        $(this).removeClass("active");
  69.     }
  70.   });
  71. });
  72. {#实时显示时间#}
  73. function showTime(){
  74. nowtime=new Date();
  75. year=nowtime.getFullYear();
  76. month=nowtime.getMonth()+1;
  77. date=nowtime.getDate();
  78. document.getElementById("mytime").innerText=year+"年"+month+"月"+date+" "+nowtime.toLocaleTimeString();
  79. }
  80. <!--定时刷新时间-->
  81. setInterval("showTime()",1000);
  82. </script>
  83. </body>
  84. </html>
1.2 vote.html
  1. {% extends 'SitesApp/base.html' %}
  2. {% block title %}
  3. <title>投票</title>
  4. {% endblock %}
  5. {% block content %}
  6. {% ifequal ip '127.0.0.1' %}
  7. <a href="{% url 'sitesApp:addCandidate' %}" style="color: green;margin: 0 0 10px;display: inline-block">新增候选者</a>
  8. {% endifequal %}
  9. <div style="width: 800px;margin: 0 auto;">
  10. {% for condidate in page.object_list %}
  11. <div style="display: inline-block;position: relative;">
  12. <span style="color: red;">{{ condidate.cName }}</span>
  13. <img src="/static/SitesApp/imgs/language/{{ condidate.cIcon }}" style="height: 60px;margin: 0 10px 10px;display: block;" title="{{ condidate.cDeclaration }}">
  14. <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>
  15. <button class="chat" chatCid="{{ condidate.id }}" title="留言"><span class="glyphicon glyphicon-envelope" title="留言"></span></button>
  16. <br>
  17. 票数:<span id="{{ condidate.id }}" class="badge">{{ condidate.cVotes }}</span>
  18. </div>
  19. {% endfor %}
  20. <br>
  21. {# 分页器:html内容拷贝于bootstrap网站-组件-分页#}
  22. {# bootstrap是一整套成熟经典的页面组件框架#}
  23. <nav aria-label="Page navigation">
  24. <ul class="pagination">
  25. {# 上一页按钮#}
  26. {# 如果有上一页#}
  27. {% if page.has_previous %}
  28. <li>
  29. {# 点击超链接,对上一页的页面发起访问#}
  30. <a href="{% url 'sitesApp:vote' page.previous_page_number %}" aria-label="Previous">
  31. <span aria-hidden="true">&laquo;</span>
  32. </a>
  33. </li>
  34. {# 如果没有上一页#}
  35. {% else %}
  36. {# 当没有上一页时,阅读bootrap文档得知,对当前li使用disabled样式#}
  37. <li class="disabled">
  38. {# href="#",处于禁用状态的按钮被点击时直接跳转本页#}
  39. <a href="#" aria-label="Previous">
  40. <span aria-hidden="true">&laquo;</span>
  41. </a>
  42. </li>
  43. {% endif %}
  44. {# 页码按钮#}
  45. {# 遍历传入的页码范围#}
  46. {% for p in pagerange %}
  47. {# 如果页码=当前页页码#}
  48. {% ifequal p currentpage %}
  49. {# 被选中的页码具有高亮效果,阅读bootrap文档得知,对当前li使用active样式#}
  50. {# {% url 'sitesApp:vote' p %} 点击页码,对第p页的路由发起访问#}
  51. <li class="active"><a href="{% url 'sitesApp:vote' p %}">{{ p }}</a></li>
  52. {% else %}
  53. {# 非当前页页码普通显示#}
  54. <li><a href="{% url 'sitesApp:vote' p %}">{{ p }}</a></li>
  55. {% endifequal %}
  56. {% endfor %}
  57. {# 下一页按钮#}
  58. {% if page.has_next %}
  59. <li>
  60. {# 点击超链接,对下一页的页面发起访问#}
  61. <a href="{% url 'sitesApp:vote' page.next_page_number %}" aria-label="Next">
  62. <span aria-hidden="true">&raquo;</span>
  63. </a></li>
  64. {% else %}
  65. {# 当没有下一页时,阅读bootrap文档得知,对当前li使用disabled样式#}
  66. <li class="disabled">
  67. {# href="#",处于禁用状态的按钮被点击时直接跳转本页#}
  68. <a href="#" aria-label="Next">
  69. <span aria-hidden="true">&raquo;</span>
  70. </a>
  71. </li>
  72. {% endif %}
  73. </ul>
  74. </nav>
  75. </div>
  76. <div style="height: 280px;width:800px;margin: 0 auto;">
  77. <h2 style="height: 20px; width: 100px;margin-bottom: 15px;">留言区</h2>
  78. <div id="chat" style="height: 200px; width: 800px;overflow: auto;border: 2px solid black;border-radius: 5px;">
  79. <table >
  80. <thead>
  81. <tr class="danger">
  82. <th style="width: 40px;text-align: center;">序号</th>
  83. <th style="width: 80px;text-align: center;">留言时间</th>
  84. <th style="width: 60px;text-align: center;">留言者</th>
  85. <th style="width: 80px;text-align: center;">标题</th>
  86. <th style="width: 550px;text-align: center;">内容</th>
  87. </tr>
  88. </thead>
  89. <tbody >
  90. {% if messages %}
  91. {% for message in messages %}
  92. <tr class="{% cycle 'active' 'success' 'warning' 'info' %}">
  93. <td> {{ forloop.counter }} </td>
  94. <td style="width: 150px;">{{ message.crDateTime|date:'Y-m-d H:i' }}</td>
  95. <td style=" padding: 0 20px;">guest{{ forloop.counter }} </td>
  96. <td style=" padding: 0 20px;">评价</td>
  97. <td style=" padding: 0 20px;">{{ message.crInfo }}</td>
  98. </tr>
  99. {% endfor %}
  100. {% else %}
  101. <tr>
  102. <td colspan="4">无数据</td>
  103. </tr>
  104. {% endif %}
  105. </tbody>
  106. </table>
  107. </div>
  108. </div>
  109. {% endblock %}
  110. {% block script %}
  111. <script type="text/javascript">
  112. /*
  113. $(this)当前被点击的元素
  114. <a style='color:black;'>你好</a>
  115. element.css('color','red')设置元素的CSS样式
  116. element.css('color')获取元素的CSS样式
  117. <a href='xxx'>你好</a>
  118. element.attr('href','http://www.baidu.com')设置元素的html属性
  119. element.attr('href')获取元素的html
  120. <a href='xxx'>你好</a>
  121. element.html('我好')设置元素的html节点内容
  122. element.html()获取元素的html节点内容
  123. */
  124. $(function($){
  125. <!--如果用户已经投过票,投票按钮就显示红色-->
  126. var isVoteLists = {{ isVoteLists }}
  127. {# console.log(isVoteLists);#}
  128. {#如果用户已经点击了就显示红色#}
  129. $('*[voteCid]').each(function () {
  130. var voteCid = $(this);
  131. if( $.inArray(parseInt(voteCid.attr('voteCid')), isVoteLists) >= 0){
  132. voteCid.css("background", "#D1191B");
  133. }
  134. });
  135. $('.vote').click(function () {
  136. var voteBtn = $(this);
  137. var cid = voteBtn.attr('voteCid');
  138. var spanGnum = voteBtn.next().next().next();
  139. $.getJSON(
  140. "{% url 'sitesApp:addVote' %}",
  141. {"cid": cid},
  142. function (data) {
  143. console.log(data);
  144. {# 投票成功#}
  145. if(data['status'] == 1){
  146. voteBtn.css("background", "#D1191B");
  147. }else if(data['status'] == 2){
  148. {#用户再次点击就显示绿色#}
  149. voteBtn.css("background", "#95D195");
  150. }
  151. spanGnum.html(data['poills'] );
  152. window.location.href = '{% url "sitesApp:vote" %}';
  153. }
  154. )
  155. });
  156. $('.chat').click(function () {
  157. var voteBtn = $(this);
  158. var whoId = voteBtn.attr('chatCid');
  159. var judge = prompt(name + "留言区(最多40个字)");
  160. if (judge && judge.length <= 40) {
  161. url = '{% url "sitesApp:chat" %}';
  162. $.ajax({
  163. type:"POST",
  164. url:url,
  165. data:{"cInfo":judge, "whoId":whoId},
  166. dataType:"json",
  167. success: function(res) {
  168. if(res['status'] == 1){
  169. window.location.href = '{% url "sitesApp:vote" %}';
  170. }
  171. }
  172. });
  173. } else {
  174. alert("留言失败");
  175. }
  176. });
  177. });
  178. </script>
  179. {% endblock %}
2 路由处理(V)
2.1 项目下的总路由
  1. urlpatterns = [
  2. url('^app/',include('SitesApp.urls',namespace='sitesApp'))
  3. ]
2.2 子应用下的路由
  1. # 投票
  2. url(r'^vote/(?P<pageNum>\d+)?', views.vote,name='vote'),
  3. # 增加投票
  4. url(r'^addVote/', views.addVote, name='addVote'),
3、视图函数处理(Views)
3.1 投票主页
  1. # 投票
  2. def vote(request,pageNum):
  3. print('要第几页数据',pageNum)
  4. if not pageNum:
  5. pageNum = 1
  6. # 获取用户IP
  7. ip = getUserIP(request)
  8. # 把本机地址传到页面,页面才能显示新增候选者按钮
  9. dictData = {'ip': '127.0.0.1'}
  10. # 获取候选者
  11. candidates = Candidate.cManager.filter(cVoteType__vType__contains='编程').order_by('-cVotes')
  12. # 用户投票结果列表
  13. isVoteLists = []
  14. for candidate in candidates:
  15. print(candidate.cName,'的票数为',candidate.cVotes)
  16. # 判断当前IP今天是否已经对该候选者投过票
  17. isVote = opeVoteRecordT.query(vCandidateId_id=candidate.id,isDelete=0,vTypeId_id=candidate.cVoteType_id, vComIP=ip,
  18. vDate=datetime.datetime.now().__format__('%Y-%m-%d'))
  19. if isVote.exists():
  20. isVoteLists.append(candidate.id)
  21. dictData['isVoteLists'] = isVoteLists
  22. # 获取留言信息
  23. chatRecords = ChatRecord.crManager.filter(crType=candidates.first().cVoteType_id)
  24. if chatRecords.exists():
  25. dictData['messages'] = chatRecords
  26. # 构建分页器对象,candidates=候选者列表,5=每页显示的个数
  27. paginator = Paginator(candidates, 5)
  28. # 获取第n页的页面对象
  29. page = paginator.page(pageNum)
  30. # Paginator和Page的常用API
  31. # page.previous_page_number()
  32. # page.next_page_number()
  33. # page.has_previous()
  34. # page.has_next()
  35. # 构造页面渲染的数据
  36. '''
  37. 渲染需要的数据:
  38. - 当前页的候选者对象列表
  39. - 分页页码范围
  40. - 当前页的页码
  41. '''
  42. if request.method == 'GET':
  43. # 当前页的候选者对象列表
  44. dictData['page'] = page
  45. # 分页页码范围
  46. dictData['pagerange'] = paginator.page_range
  47. # 当前页的页码
  48. dictData['currentpage'] = page.number
  49. return render(request, 'SitesApp/vote.html', context=dictData)
3.2 增加票数
  1. # 增加投票数
  2. def addVote(request):
  3. cid = request.GET.get('cid',None)
  4. if not cid:
  5. return JsonResponse({'status':0,'msg':'no cid'})
  6. # 获取候选者信息
  7. candidate = Candidate.cManager.get(pk=cid)
  8. poills = candidate.cVotes
  9. ip = getUserIP(request)
  10. data = {'status': 0,'msg':'vote failed'}
  11. # 判断当前IP今天是否已经对该候选者投过票
  12. isVote = opeVoteRecordT.query(vCandidateId_id=cid,vTypeId__vType__contains='编程',vComIP=ip,vDate=datetime.datetime.now().__format__('%Y-%m-%d')).first()
  13. # isDelete初始值为0,表示记录没有被逻辑删除,用户再次点击投票就把记录删除,isDelete置为1
  14. if isVote:
  15. data['status'] = 2
  16. data['msg'] = 'already voted'
  17. # isDelete为True表示取消投票
  18. if isVote.isDelete:
  19. poills += 1
  20. else:
  21. poills -= 1
  22. # 修改投票记录
  23. if not opeVoteRecordT.modify(isVote.id,isDelete= not isVote.isDelete):
  24. print('修改投票记录失败')
  25. return JsonResponse(data)
  26. print('现在是取消(True)还是投票(False)',isVote.isDelete)
  27. # 修改候选者票数
  28. if not opeCandidateT.modify(candidate.id,cVotes=poills):
  29. print('修改候选者记录失败')
  30. return JsonResponse(data)
  31. else:
  32. user=getUser(request)
  33. if not user:
  34. return JsonResponse(data)
  35. # 增加投票记录
  36. if not opeVoteRecordT.add(vUserId_id=user.id,vCandidateId_id=candidate.id,vComIP=ip,vTypeId_id=candidate.cVoteType_id,vPolls=1,vTimes=1):
  37. return JsonResponse(data)
  38. # 修改候选者票数
  39. if not opeCandidateT.modify(candidate.id,cVotes=candidate.cVotes+1):
  40. return JsonResponse(data)
  41. data['status'] = 1
  42. data['msg'] = 'success'
  43. data['poills'] = poills
  44. 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. mysql-17-procedure

    #存储过程 /* 一组预先编译好的sql语句集合,理解成批处理语句 好处: 1.提高代码重用性 2.简化操作 3.减少了编译次数并减少了和数据库服务器的连接次数,提高了效率 */ #一.创建 /* c ...

  2. Python练习题 030:Project Euler 002:偶数斐波那契数之和

    本题来自 Project Euler 第2题:https://projecteuler.net/problem=2 # Each new term in the Fibonacci sequence ...

  3. 【数量技术宅 | Python爬虫系列分享】实时监控股市重大公告的Python爬虫

    实时监控股市重大公告的Python爬虫小技巧 精力有限的我们,如何更加有效率地监控信息? 很多时候特别是交易时,我们需要想办法监控一些信息,比如股市的公告.如果现有的软件没有办法实现我们的需求,那么就 ...

  4. matlab一个figure画多个子图,和多个figure画多个图。

    参考:https://blog.csdn.net/xiaotao_1/article/details/79024488 1,一个figure画多个子图: figure(10) % define fig ...

  5. SDK测试操作文档

    准备所需材料 先把下列所需压缩包和文件传到虚拟机中. crypto-config压缩包存放order和peer节点所需要的证书文件(需要的是申请联盟链中的order和peer的证书文件) m2压缩包是 ...

  6. Redis 中 BitMap 的使用场景

    BitMap BitMap 原本的含义是用一个比特位来映射某个元素的状态.由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间 ...

  7. 解决vue、js 下载图片浏览器默认预览而不是下载

    在网页上,如果我们下载的地址对应的是一个jpg文件,txt文件等,点击链接时,浏览器默认的是打开这些文件而不是下载,那么如何才能实现默认下载呢? 后端解决 这就是Content-Disposition ...

  8. linux网络收包过程

    记录一下linux数据包从网卡进入协议栈的过程,不涉及驱动,不涉及其他层的协议处理. 内核是如何知道网卡收到数据的,这就涉及到网卡和内核的交互方式: 轮询(poll):内核周期性的检查网卡,查看是否收 ...

  9. 多测师讲解htm_L标题标签001_高级讲师 肖sir

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>百 ...

  10. 【译】自动发现 .NET 5 中代码的潜在错误

    写代码是一件令人兴奋的事情,特别是对于  .NET 开发人员来说,平台越来越智能化了.我们现在默认在 .NET SDK 中包含丰富的诊断和代码建议.在您需要安装 NuGet 包或其他独立工具来进行更多 ...