Django之BBS博客项目
一、登陆功能(验证码)
from geetest import GeetestLib from django.contrib import auth #使用极验滑动验证码的登陆 def login(request): if request.method == "POST": #初始化一个返回给ajax的字典 ret = {"status":0,"msg":""} #从提交的数据中获取用户名和密码 username = request.POST.get("username") password = request.POST.get("password") #获取验证码相关数据 gt = GeetestLib(pc_geetest_id, pc_geetest_key) challenge = request.POST.get(gt.FN_CHALLENGE, '') validate = request.POST.get(gt.FN_VALIDATE, '') seccode = request.POST.get(gt.FN_SECCODE, '') status = request.session[gt.GT_STATUS_SESSION_KEY] user_id = request.session["user_id"] if status: result = gt.success_validate(challenge, validate, seccode, user_id) else: result = gt.failback_validate(challenge, validate, seccode) #如果result有值,则验证成功,利用auth做验证 if result: user = auth.authenticate(username=username,password=password) if user: #如果用户名密码正确 auth.login(request,user) ret["msg"] = "/index/" else: ret["status"] = 1 ret["msg"] = "用户名密码错误" else: #如果验证吗错误 ret["status"] = 1 ret["msg"] = "验证码错误" return JsonResponse(ret) return render(request,"login.html",locals()) #请在官网申请ID使用,示例ID不可使用 pc_geetest_id = "b46d1900d0a894591916ea94ea91bd2c" pc_geetest_key = "36fc3fe98530eea08dfc6ce76e3d24c4" #获取滑动验证码 def get_geetest(request): user_id = 'test' gt = GeetestLib(pc_geetest_id, pc_geetest_key) status = gt.pre_process(user_id) request.session[gt.GT_STATUS_SESSION_KEY] = status request.session["user_id"] = user_id response_str = gt.get_response_str() return HttpResponse(response_str)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/mystyle.css"> </head> <body> <div class="container"> <div class="row"> <form class="form-horizontal col-md-6 col-md-offset-3 login-form"> {% csrf_token %} <div class="form-group"> <label for="username" class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="username" name="username" placeholder="用户名"> </div> </div> <div class="form-group"> <label for="password" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="password" class="form-control" id="password" name="password" placeholder="密码"> </div> </div> <div class="form-group"> <div id="popup-captcha"></div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="button" class="btn btn-default" id="login-button">登录</button> <span class="login-error"></span> </div> </div> </form> </div> </div> <script src="/static/jquery.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> <!-- 引入封装了failback的接口--initGeetest --> <script src="http://static.geetest.com/static/tools/gt.js"></script> <script> //发送数据 var handlerPopup = function (captchaObj) { // 成功的回调 captchaObj.onSuccess(function () { var validate = captchaObj.getValidate(); var username = $("#username").val(); var password = $("#password").val(); $.ajax({ url: "/login/", // 进行二次验证 type: "post", dataType: "json", data: { username: username, password: password, csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(), geetest_challenge: validate.geetest_challenge, geetest_validate: validate.geetest_validate, geetest_seccode: validate.geetest_seccode }, success: function (data) { if(data.status){ $(".login-error").text(data.msg); }else{ location.href = data.msg; } } }); }); //绑定事件显示滑动验证码 $("#login-button").click(function () { captchaObj.show(); }); // 将验证码加到id为captcha的元素里 captchaObj.appendTo("#popup-captcha"); // 更多接口参考:http://www.geetest.com/install/sections/idx-client-sdk.html }; // 验证开始需要向网站主后台获取id,challenge,success(是否启用failback) $.ajax({ url: "/pc-geetest/register?t=" + (new Date()).getTime(), // 加随机数防止缓存 type: "get", dataType: "json", success: function (data) { // 使用initGeetest接口 // 参数1:配置参数 // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件 initGeetest({ gt: data.gt, challenge: data.challenge, product: "popup", // 产品形式,包括:float,embed,popup。注意只对PC版验证码有效 offline: !data.success // 表示用户后台检测极验服务器是否宕机,一般不需要关注 // 更多配置参数请参见:http://www.geetest.com/install/sections/idx-client-sdk.html#config }, handlerPopup); } }); </script> </body> </html>
二、注册功能(ajax上传数据)
def register(request): if request.method == "POST": form_obj = RegisterForm(request.POST) ret = {"status": 0, "msg": ""} if form_obj.is_valid(): form_obj.cleaned_data.pop("re_pwd") avatar = request.FILES.get("avatar") models.UserInfo.objects.create(**form_obj.cleaned_data,avatar=avatar) return JsonResponse(ret) else: ret["status"] = 1 ret["msg"] = form_obj.errors return JsonResponse(ret) form_obj = RegisterForm() return render(request,"register.html",locals())
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/mystyle.css"> </head> <body> <div class="container"> <div class="row"> <form class="form-horizontal register-form" method="post" action="/register/" novalidate enctype="multipart/form-data"> {% csrf_token %} <div class="form-group"> <label for="{{ form_obj.username.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.username.label }}</label> <div class="col-sm-4"> {{ form_obj.username }} <span id="helpBlock2" class="help-block">{{ form_obj.username.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ form_obj.password.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.password.label }}</label> <div class="col-sm-4"> {{ form_obj.password }} <span id="helpBlock2" class="help-block">{{ form_obj.password.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ form_obj.re_pwd.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.re_pwd.label }}</label> <div class="col-sm-4"> {{ form_obj.re_pwd }} <span id="helpBlock2" class="help-block">{{ form_obj.re_pwd.errors.0 }}</span> </div> </div> <div class="form-group"> <label for="{{ form_obj.email.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.email.label }}</label> <div class="col-sm-4"> {{ form_obj.email }} <span id="helpBlock2" class="help-block">{{ form_obj.email.errors.0 }}</span> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">头像</label> <div class="col-sm-4"> <label for="id_avatar"><img id="avatar-img" src="/static/avatar/default.png"></label> <input type="file" name="avatar" id="id_avatar" style="display:none"> <span id="helpBlock2" class="help-block"></span> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="button" class="btn btn-success" id="register-btn">注册</button> </div> </div> </form> </div> </div> <script src="/static/jquery.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> <script> //获取头像,自动加载显示选中的头像 $("#id_avatar").change(function(){ //第一步、创建一个读取文件的对象 var fileReader = new FileReader(); //第二步、读取选中的文件 fileReader.readAsDataURL(this.files[0]); //读取文件需要时间,所以要等到读取完文件,再进行下一步操作 fileReader.onload = function(){ //第三步、把图片加入img标签中 $("#avatar-img").attr("src",fileReader.result) } }); //ajax上传注册信息并获取错误信息 $("#register-btn").click(function(){ //ajax上传文件,data部分必须用对象 var formData = new FormData(); formData.append("username",$("#id_username").val()); formData.append("password",$("#id_password").val()); formData.append("re_pwd",$("#id_re_pwd").val()); formData.append("email",$("#id_email").val()); formData.append("avatar",$("#id_avatar")[0].files[0]); formData.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val()); $.ajax({ url:"/register/", type:"post", //ajax上传文件需要加两个参数 processData:false, contentType:false, data:formData, success:function(data){ if(data.status){ //如果有错误,则返回错误信息 $.each(data.msg,function(k,v){ //k是键,v是值,但是v是列表,错误信息可能有多个 $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error"); }) }else{ //如果没有错误,则跳转到指定页面 location.href = "/login/" } } }) }) //输入框取得焦点时,清楚错误信息 $("form input").focus(function(){ $(this).next("span").text("").parent().parent().removeClass("has-error"); }); </script> </body> </html>
三、博客主页
配置media用户上传数据:
1、在settings中配置:
#Django用户上传的文件都叫media文件 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR,"media")
2、在url中配置:
from django.views.static import serve from django.conf import settings urlpatterns = [ #media相关路由设置 re_path(r'^media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}), ]
主页html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/mystyle.css"> <style> .box{position:relative;} .left-info {display: inline-block;width: 10%;margin-left: 85px;} .main-info {display: inline-block;width: 70%;} .right-info {display: inline-block;width: 10%;} .author-avatar{width:70px;height:70px;} .article-footer span{margin-right:10px;} .article-footer{margin-top:10px;} </style> </head> <body> //把默认导航条第一个nav标签的navbar-default改成-inverse就从白色变成黑色 {#导航条#} <nav class="navbar navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">博客项目</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> </ul> <ul class="nav navbar-nav navbar-right"> {% if request.user.username %} <li><a href="#">{{ request.user.username }}</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="/logout">注销账户</a></li> </ul> </li> {% else %} <li><a href="/login">登陆</a></li> <li><a href="/register">注册</a></li> {% endif %} </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <!-- 页面主体 --> <div class="box"> <div class="left-info"> <div class="panel panel-primary"> <div class="panel-heading">广告</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-info"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> </div> <div class="main-info"> <!-- 文章开始 --> <div class="article-list"> {% for article in article_list %} <div class="article"> <h3><a href="#">{{ article.title }}</a></h3> <div class="media"> <div class="media-left"> <a href="#"> <img class="media-object author-avatar" src="/{{ article.user.avatar }}" alt="..."> </a> </div> <div class="media-body"> <h4 class="media-heading">{{ article.desc }}</h4> </div> </div> <div class="article-footer"> <span><a href="#">{{ article.user.username }}</a></span> <span>发布于 {{ article.create_time|date:"Y-m-d H:i:s" }}</span> <span class="glyphicon glyphicon-comment">评论({{ article.comment_count }})</span> <span class="glyphicon glyphicon-thumbs-up">点赞({{ article.up_count }})</span> </div> </div> {% endfor %} </div> <!-- 文章结束 --> </div> <div class="right-info"> <div class="panel panel-primary"> <div class="panel-heading">广告</div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-info"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> Panel content </div> </div> </div> </div> <!-- 页面结束 --> <script src="/static/jquery.js"></script> <script src="/static/bootstrap/js/bootstrap.min.js"></script> <script> </script> </body> </html>
四、文章详情(点赞、评论)
def user_index(request,username): user_obj = models.UserInfo.objects.filter(username=username).first() return render(request,"user_index.html",locals())
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <style> #div_digg { float: right; margin-bottom: 10px; margin-right: 30px; font-size: 12px; width: 125px; text-align: center; margin-top: 10px; } .diggit { float: left; width: 46px; height: 52px; background-image: url('//static.cnblogs.com/images/upup.gif'); text-align: center; cursor: pointer; margin-top: 2px; padding-top: 5px; } .buryit { float: right; margin-left: 20px; width: 46px; height: 52px; background-image: url('//static.cnblogs.com/images/downdown.gif'); text-align: center; cursor: pointer; margin-top: 2px; padding-top: 5px; } .comment{ margin-top:70px; } #commentform_title { background-image: url('//static.cnblogs.com/images/icon_addcomment.gif'); background-repeat: no-repeat; padding: 0 0 0 25px; margin-bottom: 10px; } #comment-content{ width:400px; height:200px; } </style> </head> <body> {#文章#} <h2>{{ article_det.article.title }}</h2> <div>{{ article_det.content }}</div> {#点赞#} {% csrf_token %} <div class="clearfix"> <div id="div_digg"> <div class="diggit action"> <span class="diggnum" id="digg_count">{{ article_det.article.up_count }}</span> </div> <div class="buryit action"> <span class="burynum" id="bury_count">{{ article_det.article.down_count }}</span> </div> <div class="clear"></div> <div class="diggword" id="digg_tips"></div> </div> </div> {#评论列表#} <ul class="list-group"> {% for comment in comment_list %} <li class="list-group-item"> <div> <a href="">{{ forloop.counter }}楼</a> <a href="">{{ comment.user }}</a> <span>{{ comment.create_time|date:"Y-m-d H-i" }}</span> <a><span class="son-comment" username="{{ comment.user }}" pid="{{ comment.id }}">回复</span></a> </div> <div> {{ comment.content }} </div> </li> {% endfor %} </ul> {#写评论#} <div class="comment"> <div id="commentform_title">发表评论</div> <p>用户<input type="text" disabled value="{{ article_det.article.user }}"></p> <div>评论内容</div> <div> <textarea id="comment-content"></textarea> </div> <div><button id="comment-btn">提交评论</button></div> </div> <script src="/static/jquery.js"></script> <script> //点赞 $(".action").click(function(){ //判断是赞还是踩 var is_up = $(this).hasClass("diggit"); console.log(is_up) //发送数据给后端 $.ajax({ url:"/up_down/", type:"post", data:{ article_id:{{ article_id }}, is_up:is_up, csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), }, success:function (data) { if(data.status){ if(is_up){ var up_count = $("#digg_count").text() up_count = parseInt(up_count)+1 $("#digg_count").text(up_count) }else{ var down_count = $("#bury_count").text() down_count = parseInt(down_count)+1 $("#bury_count").text(down_count) } }else{ $("#digg_tips").text("已经评价过") } } }) }) pid="" //发送评论 $("#comment-btn").click(function(){ var comment = $("#comment-content").val(); if(comment!=""){ $.ajax({ url:"/comment/", type:"post", data:{ csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(), comment_content : comment, pid: pid, article_id: {{ article_det.article.pk }} }, success:function(data){ var create_time = data.create_time; var content = data.comment_content; var username = data.username; var li = '<li class="list-group-item"><div><span style="color: gray">' + create_time + '</span> <a href=""><span>' + username + '</span></a></div> <div class="con"> <p> ' + content + ' </p> </div> </li>' $(".list-group").append(li) //清空评论输入框 $("#comment-content").val(""); //清空pid pid = "" } }) } }) //回复评论 $(".son-comment").click(function(){ $("#comment-content").focus(); var v = "@" + $(this).attr("username") + "\n"; $("#comment-content").val(v); pid = $(this).attr("pid") }) </script> </body> </html>
五、添加文章(富文本编辑器)
链接:http://kindeditor.net/doc.php
from my_bbs_again import settings import json,os def uploadJson(request): obj = request.FILES.get("uploadJson_name") path = os.path.join(settings.MEDIA_ROOT,'uploadJson',obj.name) with open(path,"wb") as f: for line in obj: f.write(line) ret = {"error":0,"url":"/media/uploadJson/"+obj.name} return HttpResponse(json.dumps(ret))
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css"> <style> *{ margin:0; } .header{ width:100%;height:80px;background-color: #1b6d85;line-height: 80px; } .header h1{line-height: 80px;margin-left: 20px} </style> </head> <body> <div class="header"> <h1>{{ user_obj.blog.title }}</h1> </div> {#添加文章#} <div class="add_article"> <div>添加文章</div> <form action="" method="post"> {% csrf_token %} <div>文章标题<input type="text" name="title"></div> <textarea id="editor_id" name="content" style="width:700px;height:300px;"></textarea> <div><input type="submit"></div> </form> </div> <script src="/static/jquery.js"></script> <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script> <script charset="utf-8" src="/static/kindeditor/lang/zh-CN.js"></script> <script> KindEditor.ready(function(K) { window.editor = K.create('#editor_id',{ //添加参数 //height,width items:[ 'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste', 'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript', 'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/', 'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage', 'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak', 'anchor', 'link', 'unlink', '|', 'about' ], uploadJson: '/uploadJson/',//指定上传文件的路径 extraFileUploadParams:{ //和文件一起上传的数据,如csrftoken csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), }, filePostName: "uploadJson_name" //上传的文件的名字 }); }); </script> </body> </html>
Django之BBS博客项目的更多相关文章
- python关于Django搭建简单博客项目(详解一)
上一篇我们说了如何搭建简易博客网站,下面我们来进行详细解答.本文没有特定顺序,请结合上一篇和源代码参照学习. 相关源代码和解析请参看:https://github.com/Cheng0829/mysi ...
- python关于Django搭建简单博客项目(教程)
由于csdn各种django blog博文都有或多或少的bug,所以我决定自己写一篇,先附上教程,详解在另一篇博文里,为了便于大家复制粘贴,本文代码尽量不使用图片. 源代码及解析文章请在我的githu ...
- python关于Django搭建简单博客项目 详解二-setting.py
这一篇我们来讲解setting.py,具体内容以注释形式写入到下面的setting.py代码中,篇幅所限已把官方所给英文注释删除. 全部源代码和详解请参看http://github.com/Cheng ...
- Python Web开发:Django+BootStrap实现简单的博客项目
创建blog的项目结构 关于如何创建一个Django项目,请查看[Python Web开发:使用Django框架创建HolleWorld项目] 创建blog的数据模型 创建一个文章类 所有开发都是数据 ...
- Django——博客项目
博客项目 目前的目标是构建一个基于Django的前后端完整的博客系统,首先对项目流程整理如下: 1. 分析需求 1.1. 基于用户认证组件和Ajax实现登录验证 图形验证码核心代码: 模板: < ...
- 9.28 Django博客项目(一)
2018-9-28 17:37:18 今天把博客项目 实现了注册和添加图片的功能! 放在了自己的github上面 源码! https://github.com/TrueNewBee/bbs_demo ...
- django博客项目1.环境搭建
安装 Python Windows 下安装 Python 非常简单,去 Python 官方网站找到 Python 3 的下载地址,根据你的系统选择 32 位或者 64 位的安装包,下载好后双击安装即可 ...
- Django day17 博客项目(一)
一: 博客项目需求分析 首页(显示文章) 文章详情 点赞, 点踩 文章评论 字评论 评论的展示 登录功能(图片验证码) 注册功能(基于form验证,ajax) 个人站点(不同人不同样式,文章过滤) 后 ...
- day09搭建均衡负载和搭建BBS博客系统
day09搭建均衡负载和搭建BBS博客系统 搭建BBS博客系统 本次搭建bbs用到的技术 需要用到的: 1.Nginx+Django 2.Django+MySQL 环境准备 主机 IP 身份 db01 ...
随机推荐
- (七)Create an Index
Now let’s create an index named "customer" and then list all the indexes again: 现在让我们创建一个名 ...
- Java多线程之ReentrantLock与Condition
一.ReentrantLock 1.ReentrantLock简介 ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”.ReentrantLock 类实现了 Lock ,它拥有与 sy ...
- odoo11 访问MSQL Server等第三发数据源
odoo框架默认的访问时Postgres数据库,但在实际的应用场景中,不可避免的使用到其他数据库,所以有必要研究如何连接其他第三方数据库,这里分享下OCA的相关模块,具体的源代码在这里. 我将第三方的 ...
- 小议SQL数据插入
--数据插入操作:INSERT INTO user_info(username,age) VALUES('ZHANGSAN',20);INSERT INTO user_info(username,ph ...
- python和anacoda安装第三方库的位置
查看已安装库及版本号,命令行pip list 安装第三方库位置:
- Spring boot整合ElasticSearch案例分享+bboss
https://my.oschina.net/bboss/blog/1835601?tdsourcetag=s_pcqq_aiomsg 欢迎观看浏览
- 家庭记账本小程序之删(java web基础版四)
实现删除消费账单 1.main_left.jsp中该部分,调用Servlet中delete方法 2.Servlet中delete方法,调用Dao层list方法,跳转到del.jsp页面 3.Dao层l ...
- matplotlib使用
import numpy as np import matplotlib.pyplot as plt 生成数据 mean1=[5,5] cov1=[[1,1],[1,1.5]] data=np.ran ...
- vue独立构建和运行构建
有两种构建方式,独立构建和运行构建.它们的区别在于前者包含模板编译器而后者不包含. 模板编译器:模板编译器的职责是将模板字符串编译为纯 JavaScript 的渲染函数.如果你想要在组件中使用 tem ...
- Lodop打印控件在页面如何使用
Lodop打印控件部署到web服务器简单,在页面的使用方法也简单,是非常容易和方便使用的打印控件.客户端本地打印角色(即用户访问网站后 用自己链接的打印机进行客户端本地打印),步骤很少,部署简单:Lo ...