pip install --upgrade pip
@验证码
作用:
def main(request):
#引入绘图模块
import os
from PIL import Image, ImageDraw, ImageFont
from django.http import HttpResponse
from django.shortcuts import render
#引入随机函数模块
import random
#定义变量,用于画面的背景色,宽,高
bgcolor = (random.randrange(20,100),random.randrange(20,100),random.randrange(20,100))
width = 100
height = 50
#创建画面对象
im = Image.new('RGB',(width,height),bgcolor)
#创建画笔对象
draw =ImageDraw.Draw(im)
#调用画笔的point()函数绘制噪点
for i in range(0,100):
xy = (random.randrange(0,width),random.randrange(0,height))
fill = (random.randrange(0,255),255,random.randrange(0,255))
draw.point(xy,fill=fill)
# 定义验证码的备选值
str='1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
#随机选取4个值作为验证码
rand_str = ''
for i in range(0,4):
rand_str += str[random.randrange(0,len(str))]
#构造字体对象
font = ImageFont.truetype(r'/home/myroot/PycharmProjects/verifycode/stat/fonts/SourceHanSerifCN-ExtraLight.otf',40)
fontcolor1 = (255,random.randrange(0,255),random.randrange(0,255))
fontcolor2 = (255,random.randrange(0,255),random.randrange(0,255))
fontcolor3 = (255,random.randrange(0,255),random.randrange(0,255))
fontcolor4 = (255,random.randrange(0,255),random.randrange(0,255))
#绘制4个字
draw.text((5,2),rand_str[0],font = font,fill=fontcolor1)
draw.text((25,2),rand_str[1],font = font,fill=fontcolor2)
draw.text((50,2),rand_str[2],font = font,fill=fontcolor3)
draw.text((75,2),rand_str[3],font = font,fill=fontcolor4)
#释放画笔
del draw
#存入session,用于做进一步验证
#request.session['verifycode'] = rand_str
#内存文件操作
import io
buf = io.BytesIO()
#将突破保存在内存中,文件类型为png
im.save(buf,'png')
#将内存中的图片数据返回给客户端,MIM类型为图片png
return HttpResponse(buf.getvalue(),'image/png')
@验证码的使用
先创建一个路由指向验证码,填写表单的是时候加上验证码图片
<img src =‘指向验证码的路由’>
如果需要实现验证效果的把验证码内的
#request.session['verifycode'] = rand_str
这一行解开注释,在把提交栏内的值code1 = request.POST.get(‘提交栏的name’)和验证码的code2=request.session(‘verifycode’)比较。
@中间件
概念:一个轻量级,底层的插件,可以介入Django的请求和响应
本质:一个python类
方法:
__init__:不需要传参数,服务器响应第一个请求的时候自动调用,用于确定是否启用该中间件
process_request(self,request):在执行视图之前被调用(分配url匹配视图之前),每个请求都会调用,返回None或者HttpResponse对象,作用是判断否有异常请求,并做出处理
process_view(self,request,view_func,view_args,view_kwargs):调用视图之前执行,每个请求都会调用,返回None或者HttpResponse对象
process_template_response(self,request,response):在视图刚好执行完后调用,每个请求都会调用,返回None或者HttpResponse对象
process_response(self,request,response):所有响应返回浏览器之前调用,每个请求都会调用,返回None或者HttpResponse对象
process_exception(self,request,exception):当视图抛出异常时会调用,返回HttpResponse对象
@自定义中间件
就是面向切面编程
切点(钩子)
切点允许我们动态的在原有逻辑中插入一部分代码
在不修改原有代码的情况下,动态注入一部分代码
默认情况,不中断传播,切点会自动愈合(自动执行原有逻辑)
如果我们执行了中断操作(return,raise),没接上,会直接到程序结尾
django的中间件
#没有参数,服务器响应第一个请求的时候自动调用,用户确定是否启用该中间件
__init__
#在执行视图前被调用,每个请求上都会调用,不返回或返回HttpResponse对象
process_request(self,request)
#调用视图之前执行,每个请求都会调用,不返回或返回HttpResponse对象
process_view(self,request,view_func,view_args,view_kwargs)
#在视图刚好执行完后进行调用,每个请求都会调用,不返回或返回HttpResponse对象
process_template_response(self,request,response)
#所有响应返回浏览器之前调用,每个请求都会调用,不返回或返回HttpResponse对象
process_response(self,request,response)
#当视图抛出异常时调用,不返回或返回HttpResponse对象
process_exception(self,request,exception)
自定义的中间件
class LearnAOP(MiddlewareMixin):
def process_request(self,request):
print('request的路径',request.GET.path)
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
def process_request(self,request):
print("fet参数:",request.GET.get("a")
实现阻拦黑名单效果
第一步先在工程目录下新建一个目录自定义名为middleware,在该目录下新建一个有语义的目录比如middleware里新建一个py文件
完成之后还要在setting.py里配置一下
在MIDDLEWARE里添加
class MyappMiddleware的路径
'middleware.middleware.MyappMiddleware',
在末尾添加黑名单列表
#黑名单列表
BLACK_LIST = [
'192.168.116.1',
]
# 继承于框架中间件
class MyappMiddleware(MiddlewareMixin):
def process_request(self,request):
clientIp = request.META['REMOTE_ADDR']
# # 屏蔽黑名单用户
# 只要客户端IP在黑名单中
if clientIp in BLACK_LIST:
直接渲染fuckoff.html并立刻返回
return render(request,'fuckoff.html')
# 下钩子于所有路由请求被交给视图函数之前
def process_view(self, request, view_func, view_args, view_kwargs):
print(">>>>>>>>>> process_view", request, view_func, view_args, view_kwargs)
实现会员福利通道
包括登录
所有的钩子函数都可以返回一个Response
一旦钩子函数返回了Response,整个请求的受理就结束了
'''
# 继承于框架中间件
class MyappMiddleware(MiddlewareMixin):
# 中间件的初始化方法,全局执行一次
# def __init__(self, get_response=None):
# super(MyappMiddleware, self).__init__()
# print(">>>>>>>>>> MyappMiddlware __init__")
# 下钩子于所有路由被交给路由表之前
def process_request(self, request):
# 获取客户端IP地址
clientIp = request.META['REMOTE_ADDR']
# 请求的路由
url = request.path
print(">>>>>>>>>> process_request", request, clientIp, url)
# # 屏蔽黑名单用户
# 只要客户端IP在黑名单中
# if clientIp in BLACK_LIST:
# 直接渲染fuckoff.html并立刻返回
# return render(request,'fuckoff.html')
# # 当VIP用户访问福利页面时提供更多好的服务
# if clientIp in VIP_LIST and url=='/myapp/fuli/':
# return render(request, 'fuli.html', context={'imgpath': 'meinv1.jpg'})
# 福利页必须登录了才能查看
if url == '/myapp/fuli/' and not request.session.get('uname', None):
return redirect(reverse('myapp:login'))
# 下钩子于所有路由请求被交给视图函数之前
def process_view(self, request, view_func, view_args, view_kwargs):
print(">>>>>>>>>> process_view", request, view_func, view_args, view_kwargs)
# 理论上下钩子于所有路由请求的模板被渲染完成以后
# 这个函数实测无法回调
def process_template_response(self, request, response):
print(">>>>>>>>>> process_template_response", request, response)
return response
# 下钩子于所有路由的响应被返回之前
def process_response(self, request, response):
print(">>>>>>>>>> process_response", request, response)
return response
def process_exception(self, request, exception):
print(">>>>>>>>>> process_exception", request, exception)
return redirect('/')
@上传文件
概述:文件上传时,文件数据存储在request.FILES属性中
存储路径:
#xxx是提交上传后转到的路由
ps:提交的方式应该用post,由于get只能提交一个网址栏大小的字符串,限定了大小,而post是不限制的
接收的view:
if request.method == 'POST'
#拿到用户上传的文件数据,类型是框架类InMemoryUploadedFile
f = request.FILES['icon']
#f是文件标识符,是文件流
filePath = os.path.join(settings.MEDIA_ROOT,f.name)
with open(filePath,'wb') as fp:
#以文件流的形式接收一段一段的存进文件
for part in f.chunks():
fp.write(part)
else:
return HttpReseponse('上传失败')
@分页
paginator对象,作用是把从数据库提出来的数据进行分割,返回每一块分割好的对象
创建对象
格式:
Paginator(列表,整数)
返回值
返回一个分页对象
属性
count
对象总数
num_pages
页面总数
方法
异常
- object_list:当前页上的数据(对象)列表
- number:当前页的页码值
- paginator:当前page对象关联的page对象
方法
has_next():判断是否有下一页,如果有返回True
has_previous():判断是否有上一页,如果有返回True
has_other_pages():判断是否有上一页或下一页,如果有返回True
next_page_number():返回下一页的页码
previous_page_number():返回上一页的页码
len():返回当前页的数据的个数
过程实现:
写view
def studentpage(request,pagenum):
# 查询数据库获取所有博文
allstu = Students.object.all()
# 构建分页器对象,allstu=所有学生,3=每页显示的个数
paginator =Paginator(allstu,3)
# 获取第n页的页面对象
page = paginator.page(pagenum)
# 将数据丢给页面渲染
return render(request, 'studentshow.html', {'students':page})
写studentshow.html
<ul>
#获取页面对象
{% for stu in students %}
<li>
#遍历显示对象属性
{{stu.name}--{stu.sgrade}}
li>
{% endfor %}
ul>
<ul>
{% for index in students.paginator.page_range %}
#判断如果显示的是当前页面就不能再点击
{% if index == students.number %}
<li>{{index}}li>
{% else %}
<li>
<a href="/app/studentshow/{{ index }}/">{{ index }}a>
li>
{% endif %}
{% endfor %}
ul>
@ajax
作用:需要数据动态生成,请求JSON数据
实现过程:
html页面
#效果:点击按钮显示生成
#导入jquery的js文件
显示学生信息列表
#导入自己写的js文件
自己写的js文件
$(document).ready(function(){
document.getElementById("btn").onclick =function(){
$.ajax({
type:"get",
#提供数据的路由
url:"/studentsinfo/",
dataType:"json",
success:function(data,status){
console.log(data)
var d =data["data"]
for(var i = 0;i''+d[i][o]+'
')
}
)}
}
})
路由写法
def studentsinfo(request):
stus = Students.objects.all()
list = []
for stu in stus:
list.append([stu.sname,stu.sage])
return JsonResponse({'data':list})
返回的数据可以使用生成标签
@富文本
作用是把标签textarea标签变成文本编辑器,用于编写博客时,,,,,,
第一步
安装pip install django-tinymce
第二步
站点中使用:
1,配置setting.py中的INSTALL_APP 里添加‘tinymce’
后尾再增加
TINYMCE_DEFAULT_CONFIG={
'theme':'advanced',
'width':600,
'height':400,
#宽和高都是自定义的
}
2,新建一个Text模型
from tinymce.models import HTMLField
class Text(models,Model):
str = HTMLField()
3,数据迁移后再admin里注册一下就可以在站点管理里使用了
@自定义视图中使用
重点是html的编写
#这个JS是写死的
<script src="/static/tiny_mce/tiny_mce.js" type="text/javascript" charset="utf-8">script>
<script type="text/javascript">
tinyMCE.init({
'mode':'textareas',
'theme':'advanced',
'width':800,
'height':600
})
script>
#boby部分
<form action='提交路由'>
<textarea name=''str>文本编写的内容textarea>
form>