一、分页器
1、分页器的好处
通过分页管理多条数据,可以美化界面并能提高查询效率
2、一般方式进行分页
def get_students(request): page = int(request.GET.get("page", 1)) # 获取页码 per_page = int(request.GET.get("per_page", 10)) # 获取每页需要显示的数量 students = Student.objects.all()[per_page*(page-1): page * per_page] # 进行分页查询 data = { "students": students } return render(request, 'students.html', context=data)
3、使用分页器
from django.core.paginator import Paginator
3.1、分页器对象
(1)、实例化分页器对象
paginator = Paginator(数据源,每页最多显示的条数)
(2)、属性
count 对象总数
num_pages 页面总数
page_range 页码列表,从1开始
(3)、方法
page(page_num) 返回一个page对象,page_num为页码(整数)
3.2、页面对象
具体的某一页,由分页器的Page方法获得。
(1)、属性和方法
page_num 当前页码
object_list 当前页的数据
has_next 是否有下一页
has_previous 是否有上一页
next_page_number 下一页页码
previous_page_number 上一页页码
len() 当前页数据的个数
4、常见错误
(1)、InvalidPage
page()传递无效页码
(2)、PageNotAnInteger
page()传递的不是整数
(3)、Empty
page()传递的值有效,但是没有数据
5、实例
(1)、url
from django.urls import path from myapp.views import show_students app_name = 'myapp' urlpatterns = [ path('showstu/<pagenum>/',show_students,name='students'), ]
(2)、view
from django.core.paginator import Paginator from django.shortcuts import render from myapp.models import Student page_size = 3 #每页最多显示的条数 def show_students(request,pagenum): #pagenum是页码参数 students = Student.objects.all() #查询所有学生,返回QuerySet paginator = Paginator(students,page_size) #实例化'分页器对象',传入容器和page_size page = paginator.page(pagenum) #通过分页器对象返回Page,Page对象封装了某一页信息 page_range = paginator.page_range # 页码列表 return render(request,'students.html',locals())
(3)、html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>学生信息</title> </head> <body> <table align="center" border="1"> <tr> <th>学号</th> <th>姓名</th> <th>年龄</th> <th>成绩</th> </tr> {% for student in page %} <tr> <td>{{ student.id }}</td> <td>{{ student.name }}</td> <td>{{ student.age }}</td> <td>{{ student.score }}</td> </tr> {% endfor %} </table> <center> <a href="{% url 'myapp:students' 1 %}">首页</a> {% if page.has_previous %} <a href="{% url 'myapp:students' page.previous_page_number %}">上一页</a> {% else %} <a href="javascript:alert('已经是首页了')">上一页</a> {% endif %} {% if page.has_next %} <a href="{% url 'myapp:students' page.next_page_number %}">下一页</a> {% else %} <a href="javascript:alert('已经是末页了')">下一页</a> {% endif %} <a href="{% url 'myapp:students' paginator.num_pages %}">末页</a> </center> </body> </html>
(4)、添加bootstrap样式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/1.2.3/jquery.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.0/css/bootstrap.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.0/js/bootstrap.js"></script> </head> <body> <table align="center" border="1"> <tr> <th>学号</th> <th>姓名</th> <th>成绩</th> </tr> {% for student in page.object_list %} <tr> <td>{{ student.id }}</td> <td>{{ student.name }}</td> <td>{{ student.score }}</td> </tr> {% endfor %} </table> <center> <nav aria-label="Page navigation"> <ul class="pagination"> {% if page.has_previous %} <li> <a href="{% url 'myapp:students' page.previous_page_number %}" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% else %} <li class="disabled"> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% endif %} {% for page_index in page_range %} {% ifequal page_index page.number %} <li class="active"><a href="{% url 'myapp:students' page_index %}">{{ page_index }}</a></li> {% else %} <li><a href="{% url 'myapp:students' page_index %}">{{ page_index }}</a></li> {% endifequal %} {% endfor %} {% if page.has_next %} <li> <a href="{% url 'myapp:students' page.next_page_number %}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> {% else %} <li class="disabled"> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> {% endif %} </ul> </nav> </center> </body> </html>
二、图片验证码
防止其它人恶意注册或访问攻击
1、手动实现验证码
(1)pillow
画布Image
需要模式 RGB
尺寸 (width, height)
背景色 (10,20,30)
画笔ImageDraw
绑定画布
模式:RGB和ARGB
封装了绘制的方法:test 绘制文本
point 绘制点
line 画线
arch 圆弧形
字体ImageFront
手动指定字体
(2)、绘制流程
指定可用背景颜色
bg = (220, 220, 180) #RGB颜色
初始化画布
image = Image.new(‘RGB’,(120,30),bg)
获取画布中画笔对象
draw = ImageDraw.Draw(image, 'RGB')
随机四位验证码并绘制
a、生成4位随机字符
def generate_code(): source = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM" code = "" for i in range(4): code += random.choice(source) return code
b、创建字体
font = ImageFont.truetype(font='static/font/Fangz.ttf', size=25)
c、指定字体颜色
font_color = (random.randrange(255), random.randrange(255), random.randrange(255))
d、绘制内容
draw.text((x,y),’R’,font,fontcolor)
e、画干扰点
for i in range(10000): fill = (random.randrange(255), random.randrange(255), random.randrange(255)) xy = (random.randrange(201), random.randrange(100)) imagedraw.point(xy=xy, fill=fill)
最后生成图片或图片对象,并返回响应。
2、和用户体系绑定
验证码真实数据需要持久化
session
cookie
3、动态刷新
浏览器缓存,根据url比对,
添加随机数,让url每次都发生变更
<img width="120" height="100%" src="/user/verifycode" onclick="flushVerifyCode(this)"><br> function flushVerifyCode(img) { img.src= '/user/verifycode?tm='+Math.random(); }
4、实例
(1)、view
import random from io import BytesIO from PIL import Image, ImageFont from PIL.ImageDraw import Draw, ImageDraw def get_color(): return random.randrange(256) def generate_code(): source = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM" code = "" for i in range(4): code += random.choice(source) return code def get_code(request): # 初始化画布,初始化画笔 mode = "RGB" size = (200, 100) red = get_color() green = get_color() blue = get_color() color_bg = (red, green, blue) image = Image.new(mode=mode, size=size, color=color_bg) imagedraw = ImageDraw(image, mode=mode) imagefont = ImageFont.truetype(settings.FONT_PATH, 100) verify_code = generate_code() request.session['verify_code'] = verify_code for i in range(4): fill = (get_color(), get_color(), get_color()) imagedraw.text(xy=(50*i, 0), text=verify_code[i], font=imagefont, fill=fill) for i in range(10000): fill = (get_color(), get_color(), get_color()) xy = (random.randrange(201), random.randrange(100)) imagedraw.point(xy=xy, fill=fill) fp = BytesIO() image.save(fp, "png") return HttpResponse(fp.getvalue(), content_type="image/png")
(2)、html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.1/jquery.js"></script> </head> <body> <form action="{% url 'myapp:login' %}" method="post"> <span>用户名:</span> <input type="text" name="username" placeholder="精神精神"> <br> <span>验证码:</span><input type="text" name="verify_code" placeholder="请输入下图中的验证码"> <br> <img src="{% url 'myapp:get_code' %}"> {# <img src="#">#} <br> <button>精神一下</button> </form> </body> </html> <script> $(function () { $("img").click(function () { console.log("点到我了"); $(this).attr("src", "/myapp/get_code/?t=" + Math.random()); }) }) </script>
(3)、setting
FONT_PATH = os.path.join(BASE_DIR, 'static/fonts/ADOBEARABIC-BOLD.OTF')