BBS项目复习
注册功能
forms组件
models是models forms是forms 两者没有任何关系
只是我们认为用forms组件校验models里面的数据
通常是用来校验模型表的数据 ModelForm
1.渲染标签
2.校验数据
3.展示信息
from django import forms
class MyForm(forms.Form):
username = forms.CharField(...)
将数据当做字典传入类中
is_valid() 校验数据多传不校验少传默认下不行的
cleaned_data
errors
渲染标签三种方式(render渲染)
form_obj = MyForm() # get请求和post变量名必须是一样的
if request.method == "POST":
form_obj = MyForm(request.POST)
return render(request,'...html',locals())
1.{{ form_obj.as_p }}
2.{{ form_obj.username.label }}{{ form_obj.username }}
3.{% for foo in form_obj %}
{{foo.label}}{{foo}}
{{foo.errors.0}}
{%endfor%}
钩子函数
注册功能
1.利用forms组件渲染前端页面
1.局部钩子 校验用户名是否存在
2.全局钩子 校验密码是否一致
2.自己写前端获取用户头像
1.利用label标签能够自动指向指定的input
2.将img标签放入了label标签中,将默认的type=file框隐藏了
3.用户选择头像之后动态展示出来
"""
img标签的src的值
1.图片的路径地址
2.图片的二进制数据
3.后端url
"""
1.利用ajax给input绑定了一个change事件
2.利用内置对象FileReader读取文件
var fileReader = new FileReader();
var fileObj = $('input[type="file"]')[0].files[0];
# 交给文件阅读器读取文件内容
fileReader.readAsDataURL(fileObj) # 异步操作
# 等待文件阅读器读取完毕
fileReader.onload = function(){
$('#img_avatar').attr('src',fileReader.result)
}
3.利用ajax提交post请求
1.当用户点击提交按钮你需要做的事
1.利用form标签的内置的可序列化方法将普通获取用户输入的文本框键值对自动获取出来
$('#myform').serializeArray() # 获取到的是一个数组内部是一个个自定义对象
2.利用each循环循环取出自定义对象里面的键值对(username,password,confirm_password,email,csrfmiddlewaretoken)
3.既要传文件有要传数据 利用内置的FormData对象
循环普通键值对
var formData = new FormData();
formData.append('','')
# 添加文件数据
formData.append('my_avatar',$('input[type="file"]')[0].files[0])
4.发送formdata类型的数据 应该考虑 前后端传输数据的编码格式
ps:1.urlencoded(form与ajax默认的提交数据编码格式),2.formdata,3.application/json
data:formData
contentType:false,
processData:false,
4.post请求后端逻辑
1.将reuqest.POST中的数据直接交给forms组件校验
2.如果校验通过 cleaned_data ps:在存储数据的时候models.Userinfo.objects.create(username='',password='')
3.向将多余的键值对的去除 将文件键值对手动添加进去
4.直接将字典打散传入
5.当数据校验不通过 返回错误信息
错误信息(form_obj.errors)以json的形式返回给ajax的回调函数
forms组件在渲染input框的时候 id值有固定格式 id_字段名
6.回调函数中利用each循环手动拼接input框的id值
将错误渲染到对应的input下面的span标签中
7.健壮性功能 用户再次输入的时候 将报错信息移除
$('input').focus(function(){
$(this).next().html('').parent().removeClass('has-error')
})
登陆功能
1.手动搭建获取用户登录的前端页面 用户名 密码 验证码
2.验证码功能
ps:利用的是img标签src属性能够支持后端url书写 自动访问该url
1.直接将后端一个图片以二进制形式发送
2.利用pillow模块 动态生成图片
pip3 install pillow
from PIL import Image,ImageDraw,ImageFont
# 生成图片Image.new('RGB',(280,40),'red')/Image.new('RGB',(280,40),(255,255,255))
# 生成画笔对象 将生成好的图片对象传入ImageDraw.draw(img_obj)
# 生成字体对象 将字体文件(.ttf)和字体大小传入ImageFont.truetype(字体文件,字体大小)
# 如何生成随机验证码
ps:chr,ord
import random
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))
# 随机获取上面的一个 写到图片上
res = random.choice([upper_str,lower_str,random_int])
draw_obj.text((20+i*45,20),res,get_random(),font_obj)
code += res
# 需要将验证码存入session中以便后续的校验
request.session['code'] = code
"""
1.自动生成一个随机字符串
2.将键值对存入django自己创建session表中
ps:django session默认的超时时间 两周
3.将生成好随机字符串返回给浏览器保存
"""
3.ajax提交数据
1 先校验验证码是否一致
2 在校验用户名和密码是否正确(auth模块自动auth.authenticate(username='',password=''))
3.登陆成功之后记录用户状态 auth.login(request,user_obj)
主页
1.将网站所有的文章都展示出来
借助于django admin快速录入数据
1.createsuperuser
2.将需要操作的模型表注册到对应的应用下的admin.py文件中
admin.site.register(models.Userinfo)
3.录入数据的时候 关系绑定一定要考虑周全
eg:用户与个人站点你得手动去绑定
2.网站用的静态的资源默认放在static文件夹下
用户上传的静态文件应该单独再开一个文件夹存放(media)
3.去settings.py中配置路径
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
# 用户上传的文件就会自动方法media文件夹
4.将media文件夹暴露给用户
手动开路由
from django.views.static import serve
from BBS import settings
url(r'^media/(?P<path>.*)',serve,{'document_root':settins.MEDIA_ROOT})
5.media配置可以暴露后端任意文件夹中的资源
个人站点
1.展示的是当前用户自己写的所有文章
2.侧边栏展示
article_list # 当前用户所有的文章
1.文章标签
# 查询当前用户下的每一个标签及标签下的文章数
models.Tag.objects.filter(blog=blog).annotate(c=Count('article__id')).values_list('c','tag_name')
2.文章分类
# 同上 理
3.日期归档
# 参考的是官方文档
3.侧边栏筛选功能
1.视图函数 共用site
url(r'^(?P<username>\w+)/(?P<condition>category|tag|archive)/(?P<params>.*)/',views.site)
2.site视图函数形参修改
site(request,username,**kwargs)
3.基于当前用户所有的文章再做一层筛选 利用queryset对象可以无限制的调用queryset方法
1.判断kwargs有没有值
2.获取kwargs里面的值
condition = kwargs.get('condition')
params = kwargs.get('params')
3.判断condition从而决定按照什么条件筛选
category_id
tag__id
基于双下滑线 __year,__month
文章详情
1.模板继承 需要解决侧边栏展示的问题
2.自定义inclusion_tag
from django.template import Library
register = Library()
@register.inclusion_tag('left_menu.html')
def left_menu(username):
# 将个人站点视图函数中侧边栏相关代码直接拷贝过来 需要什么补什么
...
3.使用 {% load my_tag %} {% left_menu username %}
4.点赞点踩
1.拷贝博客园样式(html+css)
2.给赞和踩设置一个公共的类属性 然后给这个类属性绑定点击事件
3.通过$(this).hasClass()判断用户点击的是赞还是踩
4.ajax发送
5.后端接收
1.is_up是一个字符串形式的js布尔值类型
你可以利用json直接转成python布尔值
2.首先判断当前全球是否是ajax全球
3.判断用户是否登陆request.user.is_authenticated()
4.判断当前文章是否是当前用户自己写的
根据前端传过来的id值 查询出对应的文章对象
文章对象获取用户对象跟request.user比较
5.判断当前文章是否已经被当前用户点过
只需要去点赞点踩查数据 如果有值就意味着 点过
没有 就没有点过
6.数据库操作
文章表里面的普通字段
根据is_up判断是up_num还是down_num更新
点赞点踩表记录数据
user
article
is_up
6.前端渲染成功或者失败的信息
如果点赞点踩成功 你应该讲 对应的数字加1 注意数字应该先转成number类型再加一
如果错误 找到span标签 将信息填入即可
5.评论
1.根评论
1.前端页面搭建(参考博客园样式)
2.给提交按钮绑点击事件
1.将用户评论内容 当前文章id 发送给后端
2.判断是否登陆(login_required)
局部和全局配置
@login_required(login_url='/login/')
LOGIN_URL = '/login/'
3.判断是否ajax请求
4.利用事务
"""事务四大特性:ACID"""
from django.db import transaction
with transaction.atomic():
# 事务操作
3.渲染评论楼
render渲染
查询当前文章所有的评论
前端循环展示
forloop
counter0
counter
first
last
DOM临时渲染
利用ecs6新语法 模板字符串
var userName = 'jason'
`my name is ${userName}`
2.子评论
1.parent字段设置的是null=True 所以在创建数据的时候该字段传None也不会有问题
2.点击回复按钮要做的事情
1.将回复按钮对应的评论的人名渲染到textarea中
@人名
2.textarea自动聚焦 并换行
$('input').focus()
ps:将评论对应的用户名和评论id存到了回复按钮
3.将全局parentID设值
3.每次提交成功成功将parentId再次清空
4.将子评论中的@人名文本去除
1.前端利用slice去除
2.后端
5.render渲染子评论
1.判断当前评论对象是否有parant
2.跨表查询 利用parent跨自己查根评论的用户名
6.后台管理
1.只有登录的用户才能看到自己的后台管理
2.罗列出当前用户写的所有的文章
3.添加文章
"""
XSS攻击
文章简介
"""
1.kindeditor编辑器
2.直接利用form表单发送post请求
3.文章标题 文章内容 文章简介
1.利用bs4模块
from bs4 import Beautifulsoup
res = Beautifulsoup(content,'parser.html')
res = res.find_all()
for tag in res:
print(tag.name)
if tag.name == 'script':
tag.decompose()
desc = res.text[0:150]
models.Article.objects.create(...content=str(res))
4.上传图片 去文档里面找指定方法
5.编辑
6.删除
7.用户头像修改
如果用queryset的update方法 不会自动拼接avatar前缀
可以使用对象点的方式修改