simple_tag,filte,分页以及cookie和装饰器
自定义simple_tag
内置的方法
首先Django中包含了很多内置的方法:
这里通过lower实现
在views视图函数中写如下代码:
- def tp3(request):
- name= "ABCDEFG"
- return render(request,"tp3.html",{"name":name})
在urls路由关系中添加如下:
url(r'^tp3/',views.tp3),
在tp3页面中写如下:
{{ name }}
{{ name|lower }}
最后效果如下:
自定义方法
使用simple_tag的方法:
1、 在app下创建templatetags目录
2、 创建py文件
3、 创建template对象register
4、 @register.simple_tag
def func()
如果函数有参数:
def func(a1,a2)
5、 在settings配置文件注册app
6、 在页面文件顶部{%load py文件%},如果存在继承,这个要放在继承下面
7、 最后在页面使用的时候{% func %},如果有参数
{%func 2 3 %}
这里有几个问题需要注意:
1、 在app下创建templatetags目录必须为templatetags不能更改
2、 创建py文件的时候名字可以随便定义
3、 在py文件中必须写如下代码:
- from django import template
- from django.utils.safestring import mark_safe
- register = template.Library()
- @register.simple_tag
这四行代码必须有,并且的template对象register名字不能更改
按照上面的规则,在app下创建templatetags目录
然后创建一个test.py文件,代码如下:
- #AUTHOR:FAN
- from django import template
- from django.utils.safestring import mark_safe
- register = template.Library()
- @register.simple_tag
- def func():
- return 123
并在setting中添加:
tp3.html中代码如下(注意高亮部分):
- {% load test %}
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- {{ name }}
- {{ name|lower }}
- {% func %}
- </body>
- </html>
最后效果如下:
我们将test中的func改成传递参数的,如下所示:
def func(a1,a2):
return a1+a2
在tp3.html中传递参数:
{% func 5 3 %}
结果如下:
自定义filter
filter和simple_tag的方法基本一样,只需要做如下修改:
将test.py文件中@register.simple_tag替换为@register.filter
在页面中代码改为:
{{ "zhaofan" |func:"赵凡" }}
这样最终在页面的效果如下:
而这里对比filter和simple_tag,我们可以发现各有优缺点
1、其中fileter可以放在模板语言中的if条件中,而simple_tag则不能如:
{% if "zhaofan" |func:"赵凡" %}
{% endif %}
2、filter参数固定,simple_tag参数任意
分页
在前端防止因为xss而现实字符串的可以通{{ page_str|save}}
后端:可以通过导入from django.utils.safestring import mark_safe,然后page_str = mark_safe(page_str)
通过下面例子用于理解分页
这里将分页的功能封装了一个类,改类内容如下:
- #AUTHOR:FAN
- from django.utils.safestring import mark_safe
- class Page:
- def __init__(self,current_page,data_count,per_page_count=10,page_num = 7):
- '''
- :param current_page: 当前页
- :param data_count: 数据的总数目
- :param per_page_count: 每页显示的数目
- :param page_num: 显示几页内容
- '''
- self.current_page = current_page
- self.data_count = data_count
- self.per_page_count=per_page_count
- self.page_num = page_num
- @property
- def start(self):
- '''
- :return: 返回得到起始
- '''
- return (self.current_page-1)*self.per_page_count
- @property
- def end(self):
- '''
- :return: 返回结束
- '''
- return self.current_page*self.per_page_count
- @property
- def total_count(self):
- '''
- :return: 返回总页数
- '''
- v, y = divmod(self.data_count, self.per_page_count)
- if y:
- v += 1
- return v
- def page_str(self,base_url):
- '''
- :param base_url: 这里是用于自定义url前缀
- :return: 返回的为页面下端要显示的跳转页的html语言的字符串
- '''
- page_list = []
- if self.total_count < self.page_num:
- start_index = 1
- end_index = self.total_count + 1
- else:
- if self.current_page <= (self.page_num + 1) / 2:
- start_index = 1
- end_index = self.page_num + 1
- else:
- start_index = self.current_page - (self.page_num - 1) / 2
- end_index = self.current_page + (self.page_num + 1) / 2
- if self.current_page + (self.page_num + 1) / 2 > self.total_count:
- end_index = self.total_count + 1
- start_index = self.total_count - self.page_num + 1
- if self.current_page == 1:
- prev = '<a class="page" href="#">上一页</a>'
- else:
- prev = '<a class="page" href="%s?p=%s">上一页</a>' % (base_url,self.current_page - 1)
- page_list.append(prev)
- for i in range(int(start_index), int(end_index)):
- if i == self.current_page:
- temp = '<a class="page active" href="%s?p=%s">%s</a>' % (base_url,i, i)
- else:
- temp = '<a class="page" href="%s?p=%s">%s</a>' % (base_url,i, i)
- page_list.append(temp)
- if self.current_page == self.total_count:
- nex = '<a class="page" href="#">下一页</a>'
- else:
- nex = '<a class="page" href="%s?p=%s">下一页</a>' % (base_url,self.current_page + 1)
- page_list.append(nex)
- go_page = """
- <input type='text' /><a onclick="jumpTo(this,'%s?p=');">跳转</a>
- <script>
- function jumpTo(ths,base){
- var val = ths.previousSibling.value;
- location.href = base + val;
- }
- </script>
- """ %(base_url)
- page_list.append(go_page)
- page_str = "".join(page_list)
- page_str = mark_safe(page_str)
- return page_str
在views函数中调用:
- from utils import pagination
- def user_list(request):
- current_page = request.GET.get("p",1)
- current_page = int(current_page)
- page_obj = pagination.Page(current_page,len(LI))
- data = LI[page_obj.start:page_obj.end]
- page_str = page_obj.page_str("/user_list/")
- return render(request,"user_list.html",{"data":data,"page_str":page_str})
最终的效果如下:
cookie
客户端浏览器上的一个文件
以字典的方式存在
通常很多网站登录之后,网站的右上角会显示当前用户的用户名,实现例子如下:
views里写如下代码:
- def login(request):
- print(request.method)
- if request.method=="GET":
- return render(request,"login.html")
- if request.method =="POST":
- u = request.POST.get("username")
- p = request.POST.get("pwd")
- dic = user_info.get(u)
- print(u,p)
- if not dic:
- return render(request,"login.html")
- if dic["pwd"] == p:
- res = redirect("/index")
- res.set_cookie('username1',u)
- return res
- else:
- return render(request, "login.html")
- def index(request):
- #获取当前登录的用户名
- v = request.COOKIES.get("username1")
- if not v:
- return redirect("/login")
- return render(request,"index.html",{"current_user":v})
这样用户如果没有登录的情况下就不能直接访问index页面了
,并且如果用户登录之后也能显示当前用户的用户名,也就是实现了用户认证
设置Cookie:
res.set_cookie(key,value)
参数:
key 键
value=‘’ 值
max_age=None 超时时间,以秒作为单位。默认是关闭浏览器失效
expires=None 超时时间,这个是可以设置datatime
path="/" Cookie生效的路径
domain=None Cookie生效的域名
secure=False https传输
httponly=False 只能http协议传输,无法被JavaScript获取
分页改造(结合cookie)
user_list.html代码如下:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- .pagination .page{
- display: inline-block;
- padding: 5px;
- background-color: cyan;
- margin: 5px;
- }
- .pagination .active{
- background-color: blue;
- color: white;
- }
- </style>
- </head>
- <body>
- <ul>
- {% for item in data %}
- {% include 'li.html' %}
- {% endfor %}
- </ul>
- <div>
- <select id="ps" onchange="changePageSize(this)">
- <option value="10">10</option>
- <option value="20">20</option>
- <option value="30">30</option>
- <option value="40">40</option>
- </select>
- </div>
- <div class="pagination">
- {{ page_str }}
- </div>
- <script src="/static/jquery-1.12.4.js"></script>
- <script src="/static/jquery.cookie.js"></script>
- <script>
- $(function () {
- var v = $.cookie("per_page_count");
- $("#ps").val(v);
- });
- function changePageSize(ths) {
- var v = $(ths).val();
- console.log(v);
- $.cookie("per_page_count",v);
- location.reload()
- }
- </script>
- </body>
- </html>
页面效果如上,实现的功能是当通过下拉框选择不同的选项时,即每页显示的数量,这里利用了jquery的cookie,jquery.cookie.js
关于cookie的加密
前文中我们通过
res.set_cookie('username1',u)
设置cookie,其实还有一种加密的方式,即:
res.set_signed_cookie("username1",u,salt="jiami")
通过salt这个参数实现加密,同样的获取cookie的时候也需要加上salt参数才能进行解密
用户认证装饰器
FBV的装饰器用法
我们前面代码中:
- def index(request):
- #获取当前登录的用户名
- v = request.COOKIES.get("username1")
- if not v:
- return redirect("/login")
- return render(request,"index.html",{"current_user":v})
如果我们有多页面都需要判断用户是否登录,如果每个都这样写就需要写很多遍,所以这里我们可以通过装饰器实现
将上述代码进行更改:
- def auth(func):
- def inner(request,*args,**kwargs):
- v = request.COOKIES.get("username1")
- if not v:
- return redirect("/login")
- return func(request,*args,**kwargs)
- return inner
- @auth
- def index(request):
- #获取当前登录的用户名
- v = request.COOKIES.get("username1")
- return render(request,"index.html",{"current_user":v})
CBV的装饰器用法
下面是一个普通的CBV用法例子:
- from django import views
- class Order(views.View):
- def get(self,request):
- v = request.COOKIES.get("username1")
- if not v:
- return redirect("/login")
- return render(request, "index.html", {"current_user": v})
- def post(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
如果我们只对get请求做认证
- def auth(func):
- def inner(request,*args,**kwargs):
- v = request.COOKIES.get("username1")
- if not v:
- return redirect("/login")
- return func(request,*args,**kwargs)
- return inner
- from django import views
- from django.utils.decorators import method_decorator
- class Order(views.View):
- @method_decorator(auth)
- def get(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
- def post(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
这样当访问order的时候就加上了验证功能
但是这样是只给get方法加验证,如果想要给更多得方法加验证的时候,通过下面方法实现:
- def auth(func):
- def inner(request,*args,**kwargs):
- v = request.COOKIES.get("username1")
- if not v:
- return redirect("/login")
- return func(request,*args,**kwargs)
- return inner
- from django import views
- from django.utils.decorators import method_decorator
- class Order(views.View):
- @method_decorator(auth)
- def dispatch(self, request, *args, **kwargs):
- return super(Order,self).dispatch(request, *args, **kwargs)
- def get(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
- def post(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
因为CBV每次需要先执行一个dispatch方法,我们在dispatch方法上加认证,这样就相当于在所有的上面加上了认证
但是这种方法有人会觉得多写了一个dispatch方法,可以将其简化为:
- @method_decorator(auth,name="dispatch")
- class Order(views.View):
- def get(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
- def post(self,request):
- v = request.COOKIES.get("username1")
- return render(request, "index.html", {"current_user": v})
simple_tag,filte,分页以及cookie和装饰器的更多相关文章
- django之基于cookie和装饰器实现用户认证
示例1 # Create your views here. user = "a" pwd = "a" def login(request): if reques ...
- 第二十一章 Django的分页与cookie
第二十一章 Django的分页与cookie 第一课 模板 1.模板的继承 在Template目录下新建模板master.html <!DOCTYPE html> <html lan ...
- Django之Cookie Session详解,CBV,FBV登陆验证装饰器和自定义分页
Cookie Session和自定义分页 cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接 ...
- Django(五)母版继承、Cookie、视图装饰器等
大纲 一.内容回顾 补充:默认值 补充:命名空间 二.模板语言 1.母版继承 2.include 3.自定义simple_tag 三.Cookie Cookie 使用总结 四.视图 1.获取用户请求相 ...
- [Python自学] day-21 (2) (Cookie、FBV|CBV装饰器)
一.什么是Cookie 1.什么是Cookie? Cookie是保存在客户端浏览器中的文件,其中记录了服务器让浏览器记录的一些键值对(类似字典). 当Cookie中存在数据时,浏览器在访问网站时会读取 ...
- (26)基于cookie的登陆认证(写入cookie、删除cookie、登陆后所有域下的网页都可访问、登陆成功跳转至用户开始访问的页面、使用装饰器完成所有页面的登陆认证)
获取cookie request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age ...
- cookie,session 的概念以及在django中的用法,以及cbv装饰器用法
cookie的由来: 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后 ...
- Cookie与Session、CBV添加装饰器
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- Python之路Day21-自定义分页和cookie
本节知识点概要 1.URL 2.views - 请求其他信息 - 装饰器 3.Templates - 母版 - 自定义 4.Models操作 5.分页(自定义分页) 6.cookie 7.sessio ...
随机推荐
- C# 使用Log4Net记录程序日志
在之前的博客中,写过使用系统内置的Trace类记录程序日志,具体请参考:C# 使用Trace记录程序日志.这篇博客将介绍如何使用Log4Net记录程序日志. 首先需要引用Log4Net.dll,我们可 ...
- ubuntu下配置jdk
1.首先下载jdk-7u51-linux-i586.tar.gz.并将它放在例如/home目录. 2.解压安装 sudo tar zxvf ./jdk-7u51-linux-i586.tar.gz ...
- 《DSP using MATLAB》示例Example5.16
代码: x1 = [1,2,2,1]; x2 = [1,-1,-1,1]; x3 = conv(x1,x2); % N = 5 n1 = 0:1:length(x1)-1; n2 = 0:1:leng ...
- Session和Cache的区别
以前实现数据的缓存有很多种方法,有客户端的Cookie,有服务器端的Session和Application.其中Cookie是保存在客户端的一组数据,主要用来保存用户名等个人信息.Session则保存 ...
- 【Ajax 基础学习】
http://www.cnblogs.com/guduoduo/p/3681296.html 今天简单的学习了 Ajax 的基础知识,总结在这里.部分代码不是原创,特此说明. [Ajax 简介] AJ ...
- [转]netty对http协议解析原理
本文主要介绍netty对http协议解析原理,着重讲解keep-alive,gzip,truncked等机制,详细描述了netty如何实现对http解析的高性能. 1 http协议 1.1 描述 标示 ...
- bzoj1057: [ZJOI2007]棋盘制作--最大子矩阵
既然要求最大01子矩阵,那么把应该为0的位置上的数取反,这样就变成求最大子矩阵 最大子矩阵可以用单调栈 #include<stdio.h> #include<string.h> ...
- mysql求最大第二,最大第三个数
题目是这样的: 集团有多个部门,部门下有多个员工,求每个部门绩效排名第二的人员 sql语句是这样的 SELECT dep, MAX(score) FROM zx WHERE score NOT IN ...
- Ajax调用Conrtoller返回数据
前端ajax function doRefund(){ $.ajax({ type: "POST", catch: false, url: "@Url.Action(&q ...
- Get请求中文乱码的几种解决方式
1.将字符串转码:new String("xxxxx".getBytes("iso-8859-1"),"utf-8") 这种 ...