##Django内置分页
#分页工具资源链接:dataTables (https://datatables.net)
#1、导入django类生成对象之后的方法 # 内置分页需要导入django中的类 from django.core.paginator import Paginator paginator = Paginator(user_list,10) # 第一个参数是我们查出来的所有的对象, 第二个参数表示的是每页显示的行数 # 生成一个paginator对象 paginator可以点出如下的方法 # per_page: 每页显示条目的数量(多少行) # count: 总数据的个数 # num_pages: 总页数 # page_range: 总页数的索引范围,eg: (1,10) 表示第1页到第10页 # page: page对象 users = paginator.page(cur_page) # 需要把当前页数传进去 # 生成page对象,page对象有如下的方法 # has_next 是否有下一页 # next_page_number 下一页的页码 # has_previous 是否有上一页 # previous_page_number 上一页的页码 # object_list 分页之后的数据列表QuerySet 列表中套对象 # number 当前页 # paginator paginator对象 #2、后端代码(逻辑函数) def test(request): try: # 首先我们需要从前端获取到需要指定的当前页数 cur_page = request.GET.get("cur_page") # 转成int类型 cur_page = int(cur_page) except Exception as e: cur_page=1 # 查出所有的对象 user_list = models.UserInfo.objects.all() # 内置分页需要导入django中的类 from django.core.paginator import Paginator paginator = Paginator(user_list,10) users = paginator.page(cur_page) # 需要把当前页数传进去 # 然后就可以把page对象(users)传到前台进行操作 return render(requset,"test.html",{"users":users}) #3、前端页面分页处理(页面访问:http://127.0.0.1:8000/custom/?cur_page=3) {#①先把数据生成#} <ul> {% for user in users %} <li>{{ user.name }}</li> {% endfor %} </ul> {#上一页 需要判断有没有上一页,有了才跳转#} {% if users.has_previous %} <a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {#②生成页面编号#} <li> {#users(page对象)没有总共多少页的属性,但是(paginator对象有)#} {% for num in users.paginator.page_range %} <a href="/test2/?cur_page={{ num }}">{{ num }}</a> {% endfor %} </li> {#③生成上一页与下一页#} {% if users.has_next %} <a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a> {% else %} <a href="#"></a> {% endif %}
##自定义分页
#由于django系统提供的分页功能有限,不能指定显示多少页,也不能定制一些其他东西, 所以我们自定制分页的类
def custom(request): cur_page = request.GET.get('cur_page') #获取当前页码数 #算出总行数 totle = models.UserInfo.objects.count() pageinfo = PageInfo(cur_page,totle) #实例化一个对象 start=pageinfo.get_start() stop = pageinfo.get_stop() user_list = models.UserInfo.objects.all()[start:stop] return render(request,"custom.html",{"user_list":user_list,"pageinfo":pageinfo})
class PageInfo: def __init__(self,cur_page,totle,per_page=10,show_page=11): try: self.cur_page = int(cur_page) #当前页码数 except Exception as e: self.cur_page = 1 self.per_page = per_page #每页面显示10条数据 self.show_page = show_page #每页面展示11页 # 这里用到内置函数divmod----相当于(a//b,a%b)整除和取模 # 总行数 / 每页的行数 a 表示正数部分 b表示余数 a,b =divmod(totle,per_page) if b: self.total_page = a + 1 else: self.total_page = a def get_start(self): return (self.cur_page - 1 ) * self.per_page def get_stop(self): return self.cur_page * self.per_page def page(self): half = int((self.show_page) /2) #当前页码数的前面展示多少依据 #总页数小于show_page == 11 if self.total_page < self.show_page: begin =1 stop = self.total_page +1 else: #总页数大于show_page == 11 if self.cur_page -1 < half: #比较依据原因是当前页码小于half时 出现负数页码 begin = 1 stop = self.show_page +1 elif self.cur_page + half > self.total_page: # begin = self.cur_page - half #如果当前页减去half的话,页面上的页码数随之减少,即没有显示固定11页 begin = self.total_page - self.show_page +1 stop = self.total_page+1 else: begin =self.cur_page - half stop = self.cur_page +half+1 sli = [] #添加上一页a标签,判断是否是第一页,第一页的话只能跳转到当前页,不是的话当前页减去1 进行跳转 if self.cur_page ==1: # s = "<a style='dispaly:inline-block;padding:5px;margin:5px' href='#'>上一页</a>" s = "<li class='disabled'><a href='#'>上一页</a></li>" else: # s = "<a style='dispaly:inline-block;padding:5px;margin:5px' href='/custom/?cur_page=%s'>上一页</a>" %(self.cur_page -1) s = "<li><a href='/custom/?cur_page=%s'>上一页</a></li>" %(self.cur_page -1) sli.append(s) for num in range(begin,stop): if num == self.cur_page: # s = "<a style='dispaly:inline-block;padding:5px;margin:5px;backgroud-color:red' href='/custom/?cur_page=%s'>%s</a>"%(num,num) s = "<li class='active'><a href='/custom/?cur_page=%s'>%s</a></li>"%(num,num) else: # s = "<a style='dispaly:inline-block;padding:5px;margin:5px' href='/custom/?cur_page=%s'>%s</a>" % (num, num) s = "<li ><a href='/custom/?cur_page=%s'>%s</a></li>" % (num, num) sli.append(s) # 添加下一页a标签,判断是否是最后一页,最后一页只能跳转到当前页,不是的话当前页加上1进行跳转 if self.cur_page ==self.total_page: # s = "<a style='dispaly:inline-block;padding:5px;margin:5px' href='#'>下一页</a>" s = "<li class='disabled'><a href='#'>下一页</a></li>" else: # s = "<a style='dispaly:inline-block;padding:5px;margin:5px' href='/custom/?cur_page=%s'>下一页</a>" %(self.cur_page +1) s = "<li><a href='/custom/?cur_page=%s'>下一页</a></li>" %(self.cur_page +1) sli.append(s) # 页面导航整体返到外面 page_str =" ".join(sli) return page_str
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} <nav aria-label="Page navigation"> <ul class="pagination"> {#需要把这xss改成safe 通过管道符 safe,这样插进来的html字符串才能被浏览器解析#} {{ pageinfo.page | safe }} </ul> </nav> </body> </html>
##网页攻击
#Xss攻击 #1、原理 xss攻击为跨站脚本攻击,主要原因是用户输入的内容不可控形式为在别人的评论区, 或者留言板写入js代码并且提交,如果我们不添加防护措施,就会造成,输入的 js代码会被浏览器解析执行,从而让别人获取到我们浏览器中的信息 #2、代码 django中是默认有xss保护的, 如果我们想要取消xss保护,通关 管道符 加上 safe 前端接收参数 {{ page_info | safe }} 后端直接传入js代码, 就可以被浏览器解析执行
#CSRF攻击 #1、原理 csrf攻击为跨站伪造攻击 当我们访问了不受信任的网站时,某一个图片或者连接很有可能会将我们浏览器的一些信息发送到黑客的电脑上,然后他们伪造我们去一些受信任的网站对我们的账号进行一些操作(可以轻松拿到我们的cookie)由此可见,普通的cookie验证防护不了这种csrf攻击,因此我们通过服务器给浏览器发送一个token字符串进行认证。 #2、开启csrf验证 a. settings中打开注释 'django.middleware.csrf.CsrfViewMiddleware', b. 前端表单中开启csrf_token <form action=""> {% csrf_token %} <input type="text"> </form> 如上,我们每次请求时,服务器都会在我们的表单中添加一个隐藏的token <input type="hidden" name="csrfmiddlewaretoken" value="dATM2S3fMmKrzm3wKJO23RnNRuz0mGNqBpfe7tLe5BAlWIDi8tyCS4ilkmm7WmCY"> 会在我们下一次提交数据时带上这个token,如果和服务器的相同,就说明我们时真用户 #3、当我们开启csrf认证后,想要让部分业务逻辑关闭csrf认证 from django.views.decorators.csrf import csrf_exempt # 先导入csrf_exempt @csrf_exempt def test2(request): pass 这样即便开启了全局csrf认证,也能通过装饰器关闭test2的csrf认证 #4、当我们关闭csrf认证后,想要让部分业务逻辑开启csrf认证 from django.views.decorators.csrf import csrf_protect # csrf_protect @csrf_protect def test2(request): pass 这样即便关闭了全局csrf认证,也能通过装饰器开启test2的csrf认证 #5、CBV装饰器的使用 我们上面演示的都是FBV,如果是CBV from django.views.decorators.csrf import csrf_protect,csrf_exempt from django.utils.decorators import method_decorator #csrf_protect 表示关闭的全局csrf认证, 开启部分csrf认证 #csrf_exempt 表示开启全局csrf认证, 关闭部分csrf认证 # name 表示只使用于某种提交的方式 @method_decorator(csrf_exempt,name="get") class Test(object): def get(self): pass def post(self): pass #6、ajax提交token的方式 <script> {# 首先我们要获取到token#} {#通过属性选择器找到存放token值的标签 $("input[name='csrfmiddlewaretoken']") #} csrf_token = $("input[name='csrfmiddlewaretoken']").val(); $.ajax({ type:"post", url:"/test2/", {#token放在headers中提交过去,并且headers里面的key时固定的#} headers:{"X-CSRFToken":csrf_token}, success:function () { } }) </script>