Django项目BBS博客论坛
BBS 项目开发逻辑梳理
第一步:先进行数据库设计
数据库设计规则是:
1.先创建基表:用户表、站点表、文章表、标签表、分类表、文章2标签第三张关系表、点赞点踩表、评论表
2.书写表中的基本含有的字段
3.添加外键(一对一,一对多,多对多)
4.第三张关系表
注意事项:创建外键关系的时候,to=\'表名\',不要忘记引号,null=true,并不是所有的外键都加的
第二步settings配置
一定要进行settings的相关配置:
1.数据库配置
DATABASES = {
\'default\': {
\'ENGINE\': \'django.db.backends.mysql\',
\'NAME\': \'bbszikao\',
\'USER\':\'root\',
\'PASSWORD\': \'root\',
\'HOST\':\'127.0.0.1\',
\'PORT\':3306,
\'CHARSET\':\'utf8\'
}
}
2.静态文件资源配置
STATICFILES_DIRS=[
os.path.join(BASE_DIR,\'static\')
]
3.models.py文件中,用户表继承AbstractUser类,需要对其进行settings配置
from django.contrib.auth.models import AbstractUser
配置auth模块的访问:
AUTH_USER_MODEL=\'app01.Userinfo\'
4.静态图片资源settings配置+urls路由访问配置,暴露给用户查看,用户注册可以访问到默认头像
#settings文件配置:
MEDIA_ROOT=os.path.join(BASE_DIR,\'media\')
#urls文件访问头像路由配置
url(r\'^media/(?P<path>.*)\', serve, {\'document_root\': settings.MEDIA_ROOT}),
第三步功能开发
注册功能
后端开发逻辑:
分为:register函数+register.html+myform.py文件
后端开发逻辑:
# myform.py 文件
1.建立myform.py文件,利用forms表单,提交注册的数据信息
创建class MyRegForm(forms.Form):类
用户名,密码,确认密码,邮箱
建立局部钩子函数校验用户名是否存在
建立全局钩子函数校验密码是否一致
# models.py 文件
2.把myform文件中的MyRegForm表单对象拿到,
然后把form_obj对象发送给前端register.html页面
form_obj=myform.MyRegForm()
return render(request,\'register.html\',locals())
后端开发逻辑如下:
把myform文件中的MyRegForm表单对象拿到
判断前端发送过来的请求方式是不是post请求
定义back_dic 字典
对用户在前端提交的post数据进行校验,生成form_obj对象
如果数据合法:
获取键值对
pop掉确认密码键值对
获取前端发送的文件请求(avatar),创建文件对象
判断用户是否上传文件:
上传文件了,把avatar添加到clean_data字典对象中
用户表创建用户(create_user)
back_dic字典添加msg信息,注册成功
back_dic字典添加url,login路径
数据不合法:
字典添加code=2000
字典添加msg=form_obj.errors
返回json数据到前端,[需要导入JsonResponse模块(from django.http import JsonResponse)]
然后把form_obj对象发送给前端register.html页面
前端开发逻辑:
上传头像文件功能,注册按钮功能
前端开发逻辑:register.html文件,前端只整理需要整理的
上传头像文件功能
<script>
//上传头像文件相关的处理
$(\'#mdd\').on(\'change\',function () {
//利用内置对象filereader完成文件的读取操作
let MyFileReader=new FileReader();
//获取用户上传的文件对象
let fileobj=$(this)[0].files[0];
//让文件阅读器读取文件,IO操作,异步
MyFileReader.readAsDataURL(fileobj);
//将读取之后的内容替换到img标签src属性中
MyFileReader.onload=function () {
$(\'#img\').attr(\'src\',MyFileReader.result)
}
});
// 注册按钮
$(\'#submit\').click(function () {
// 将用户输入的数据全部发送给后端 普通的键值对 文件
let MyFormData = new FormData();
// 不停的朝里面添加键值对
{#MyFormData.append(\'\',\'\')#}
{#console.log($(\'#myform\').serializeArray())#}
// 普通键值对添加完毕 (利用form标签内部有一个自动序列化普通键值对方法)
$.each($(\'#myform\').serializeArray(),function (index,obj) {
MyFormData.append(obj.name,obj.value)
});
// 手动添加文件数据
MyFormData.append(\'avatar\',$(\'#mdd\')[0].files[0]);
// 发送ajax请求
$.ajax({
url:\'\',
type:\'post\',
data:MyFormData,
// 发送文件一定要指定两个参数
processData:false, // 不要让浏览器处理你的数据
contentType:false, // 不要使用任何的编码 django能够识别对象自身
success:function (data) {
if (data.code == 1000){
// 跳转到登录页面
window.location.href = data.url
}else{
$.each(data.msg,function (index,obj) {
{#console.log(index,obj)#} // index就是报错字段 obj就是错误信息 数组的形式
// 获取报错字段 手动拼接出该字段所对应的input框的id值
let targetId = \'#id_\' + index;
$(targetId).next().text(obj[0]).parent().addClass(\'has-error\')
})
}
}
})
});
// input框获取焦点事件,---这个是鼠标放到input框上面后,错误信息消失
$(\'input\').focus(function () {
$(this).next().text(\'\').parent().removeClass(\'has-error\')
})
</script>
图片验证码功能
后端开发逻辑
1.所需要的模块
import random
from PIL import Image,ImageDraw,ImageFont
from io import BytesIO,StringIO
\'\'\'
内存管理器模块:
BytesIO 保存数据,并且在获取的时候,是以二进制的方式给你
StringIO 保存数据,并且在获取的时候,是以字符串的方式给你
Image 生成图片
ImageDraw 在图片上写字
ImageFont 控制字的字体样式
\'\'\'
#io_obj=BytesIO() #你就将该对象看成是文件句柄即可
\'\'\'
什么是文件句柄???
在文件I/O中,要从一个文件读取数据,应用程序首先
要调用操作系统函数并传送文件名,并选一个到该文件
的路径来打开文件。该函数取回一个顺序号,即文件句柄
(file handle),该文件句柄对于打开的文件是唯一的
识别依据。要从文件中读取一块数据,应用程序需要调用
函数ReadFile,并将文件句柄在内存中的地址和要拷贝的
字节数传送给操作系统。当完成任务后,再通过调用系统函数
来关闭该文件。”
\'\'\'
2.图片验证码的开发分为两步:
随机取色+图片验证码
2.1随机取色
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
2.2图片验证码函数
图片的宽高和随机取色---生成画板对象 Image.new
将生成好的图片对象交给ImageDraw---画笔对象 ImageDraw.Draw
字体样式 ---何种字体 ImageFont.truetype
#随机验证码 ---何种要求(大小写英文加数字,5位)
定义code=\'\'
循环5次:
大写字母 upper_str
小写字母 lower_str
str(随机数) random_int
随机选取一个,random.choice([大写,小写,str(随机数)])
往图片上写一个验证码 img_draw.text
存储写的字 code+=tmp
将code存到session中,供全局函数访问 request.session[\'code\']=code
生成I/O文件句柄 io_obj=BytesIO()
图片对象调用save方法保存io_obj文件对象,png的格式进行保存 img_obj.save(io_obj,\'png\')
return HttpResponse(io_obj.getvalue())
--------------------------------------------------------------------------------
3.图片验证码代码如下:
def get_code(request):
# 图片的宽高和随机取色 ----画板
img_obj=Image.new(\'RGB\',(360,35),get_random())
#将生成好的图片对象交给ImageDraw ---画笔
img_draw=ImageDraw.Draw(img_obj)
#字体样式 ---何种字体
img_font=ImageFont.truetype(\'static/font/111.ttf\',30)
#随机验证码 ---何种要求(大小写英文加数字,5位)
code=\'\'
for i in range(5):
upper_str=chr(random.randint(65,90))
lower_str=chr(random.randint(97,122))
random_int=str(random.randint(0,9))
#随机选取一个
tmp=random.choice([upper_str,lower_str,random_int])
#往图片上写一个验证码
img_draw.text((i*60+60,0),tmp,get_random(),img_font)
#存储写的字
code+=tmp
print(code)
#这个验证码后面其他视图函数可能要用到,
#找个地方存一下,并且这个地方全局的视图函数都能访问
request.session[\'code\']=code
io_obj=BytesIO() #你就将该对象看成是文件句柄即可
\'\'\'
在文件I/O中,要从一个文件读取数据,应用程序首先
要调用操作系统函数并传送文件名,并选一个到该文件
的路径来打开文件。该函数取回一个顺序号,即文件句柄
(file handle),该文件句柄对于打开的文件是唯一的
识别依据。要从文件中读取一块数据,应用程序需要调用
函数ReadFile,并将文件句柄在内存中的地址和要拷贝的
字节数传送给操作系统。当完成任务后,再通过调用系统函数
来关闭该文件。”
\'\'\'
img_obj.save(io_obj,\'png\')
return HttpResponse(io_obj.getvalue())
图片验证码实时刷新功能
前端开发逻辑
图片验证码随机变化的逻辑其实很简单,就是:
首先为验证码绑定点击事件,
其次拿到img中的src属性,
最后为src设置新的值,使得图片验证码不断的更换
<div class="col-md-6">
<img src="/get_code/" alt="" width="360" height="35" id="id_img">
</div>
<script>
//拿到img中的src,
//然后为src设置新的值,使得图片验证码不断的更换
$(\'#id_img\').click(function () {
var oldPath = $(this).attr(\'src\');
$(this).attr(\'src\',oldPath+=\'?\')
});
</script>
登录功能
后端开发逻辑
urls.py文件中:
# 登录功能
url(r\'^login/\',views.login,name=\'login\'),
views.py文件中:
开发逻辑如下:
如果请求方式是post请求:
定义back_dic
获取post请求的用户名
获取post请求的密码
获取post请求的验证码
#先校验验证码是否正确,忽略大小写
#再校验用户名和密码是否正确
如果用户输入的验证码和后端保存的验证码相等:
再用auth模块校验用户名和密码是否相等,生成用户对象
如果相等:
利用auth模块保存用户对象的登录状态
#就可以在任意位置通过request.user获取到当前登录对象,并且request.user.is_authenticated()判断当前用户是否登录
back_dic字典添加msg登录成功
back_dic字典添加url,home主页路径
如果用户名和密码不相等:
back_dic字典添加code=2000
back_dic字典添加msg用户名或密码错误
如果验证码不相等:
back_dic字典添加code=3000
back_dic字典添加msg,验证码错误
通过JsonResponse返回字典
返回到登录页面
# 保存用户登录状态,这个不太会,对该知识点模糊要多注意了,
# 通过auth模块的login方法将用户保存起来,就可以在任意位置通过request.user,
# 获取到当前登录对象,并且可以通过request.user.is_authenticated()判断当前用户是否登录
auth.login(request, user_obj)
auth模块很重要需要多复习复习
前端开发逻辑
为登录按钮绑定点击事件,
利用ajax请求,把数据发送到后端
ajax的固定格式为:
$.ajax({
url:\'\',
type:\'post\',
data:{k,v键值对,\'csrfmiddlewaretoken\':\'{{ csrf_token }}\'},
success:function(data){
//此处的data就是后端返回过来的back_dic字典对象
如果code=1000:
跳转到对应页面的url连接
如果不等于1000:
渲染错误数据信息
信息错误后自动刷新验证码
}
})
提交post请求跳过csrf中间件拦截的两种方式:
{% csrf_token %} ------- 在form表单中书写
\'csrfmiddlewaretoken\':\'{{ csrf_token }}\' ------- 在ajax中的data字典中书写
<div>
<input type="button" class="btn btn-primary" value="登录" id="id_submit">
<span style="color: red;" id="id_error"></span> //在此处渲染页面的错误信息
</div>
<script>
$(\'#id_submit\').click(function () {
$.ajax({
url:\'\',
type:\'post\',
data:{
//$(\'#标签名\').val()是获取当前标签的值
\'username\':$(\'#id_username\').val(),
\'password\':$(\'#id_password\').val(),
\'code\':$(\'#id_code\').val(),
\'csrfmiddlewaretoken\':\'{{ csrf_token }}\'
},
success:function (data) {
if(data.code == 1000){
// 跳转链接
window.location.href = data.url
}else{
//渲染错误数据信息
$(\'#id_error\').text(data.msg);
//数据填写错误,提交后验证码再次刷新
var oldPath = $(\'#id_img\').attr(\'src\');
$(\'#id_img\').attr(\'src\',oldPath+=\'?\')
}
}
})
</script>
首页搭建功能
后端开发逻辑
#home主页
第一步:查询所有文章,生成文章queryset对象,
第二步:把数据全部提交到home页面
def home(request):
#查询所有文章,生成文章queryset对象,
#把数据全部提交到home页面
article_queryset=models.Article.objects.all()
return render(request,\'home.html\',locals())
前端开发逻辑
主页搭建共分为四块,
第一块,导航条
第二块,左侧面板 2
第三块,中间面板 8
第四块,右侧面板 2
退出登录功能
后端开发逻辑
导入auth模块,导入登录认证装饰器:
from django.contrib import auth
from django.shortcuts import reverse
from django.contrib.auth.decorators import login_required
给退出登录函数添加@login_required装饰器,装饰器不要加括号
利用auth模块的退出登录函数 ---auth.logout(request)
返回通过重定向反转解析到home主页 ---redirect(reversed(\'home\'))
代码如下:
@login_required
def logout(request):
auth.logout(request)
return redirect(reverse(\'home\')) ---退出登录之后跳转到home主页
注意事项,此处是reverse,可不要写成reversed
前端开发逻辑
用户登录情况下:
展示用户名:
拿到用户的用户名,------超链接;通过auth模块的is_authenticated判断用户是否已经登录
修改密码
修改头像
后台管理
退出登录
未登录情况下:
展示登录 --超链接,反向解析login,{% url \'login\' %}
展示注册 --超链接,反向解析register,{% url \'register\' %}
部分逻辑代码如下:
{% if request.user.is_authenticated %}
<li><a href=\'#\'> {{ request.user.username }} </a></li>
<li><a data-target="#myModal" data-toggle="modal">修改密码</a></li>
<li><a href="#">修改头像</a></li>
<li><a href="#">后台管理</a></li>
<li role="separator" class="divider"></li>
<li><a href="{% url \'logout\' %}">退出登录</a></li>
{% else %}
<li><a href="{% url \'login\' %}">登录</a></li>
<li><a href="{% url \'register\' %}">注册</a></li>
{% endif %}
修改密码功能
后端开发逻辑
urls.py文件中开设修改密码的路由
url(r\'^set_password/\',views.set_password,name=\'set_pwd\')
views.py文件
from django.shortcuts import reverse
from django.contrib import auth
from django.contrib.auth.decorators import login_required
首先给修改密码函数添加装饰器@login_required
如果前端请求方式是post请求:
获取前端发送过来的原密码old_password
获取前端发送过来的新密码new_password
获取前端发送过来的确认密码confirm_password
#利用auth模块先判断前端发送过来的原密码是否正确,
#check_password是auth模块自带的校验密码是否相等的功能
request.user.check_password(old_password)
如果原密码正确:
如果新密码和确认密码相等:
利用auth模块中的set_password设置新的密码
然后利用auth模块中的save方法进行保存
返回重定向解析到登录页面
如果新密码和确认密码不相等:
返回文本,两次密码不一致
如果原密码不正确:
返回文本,原密码错误
前端开发逻辑
利用form表单,发送post请求
反向解析到set_pwd路径下,{% url \'set_pwd\' %}
利用{% csrf_token %} 跳过csrf中间件
下面就是form表单中的5个div,分别是:
用户名,使用disable属性,默认展示用户名不支持修改
原密码
新密码
确认密码
取消,修改
版权声明:本文为ludundun原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。