自定义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和装饰器的更多相关文章

  1. django之基于cookie和装饰器实现用户认证

    示例1 # Create your views here. user = "a" pwd = "a" def login(request): if reques ...

  2. 第二十一章 Django的分页与cookie

    第二十一章 Django的分页与cookie 第一课 模板 1.模板的继承 在Template目录下新建模板master.html <!DOCTYPE html> <html lan ...

  3. Django之Cookie Session详解,CBV,FBV登陆验证装饰器和自定义分页

    Cookie Session和自定义分页   cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接 ...

  4. Django(五)母版继承、Cookie、视图装饰器等

    大纲 一.内容回顾 补充:默认值 补充:命名空间 二.模板语言 1.母版继承 2.include 3.自定义simple_tag 三.Cookie Cookie 使用总结 四.视图 1.获取用户请求相 ...

  5. [Python自学] day-21 (2) (Cookie、FBV|CBV装饰器)

    一.什么是Cookie 1.什么是Cookie? Cookie是保存在客户端浏览器中的文件,其中记录了服务器让浏览器记录的一些键值对(类似字典). 当Cookie中存在数据时,浏览器在访问网站时会读取 ...

  6. (26)基于cookie的登陆认证(写入cookie、删除cookie、登陆后所有域下的网页都可访问、登陆成功跳转至用户开始访问的页面、使用装饰器完成所有页面的登陆认证)

    获取cookie request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age ...

  7. cookie,session 的概念以及在django中的用法,以及cbv装饰器用法

    cookie的由来: 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后 ...

  8. Cookie与Session、CBV添加装饰器

    cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...

  9. Python之路Day21-自定义分页和cookie

    本节知识点概要 1.URL 2.views - 请求其他信息 - 装饰器 3.Templates - 母版 - 自定义 4.Models操作 5.分页(自定义分页) 6.cookie 7.sessio ...

随机推荐

  1. singleton pattern的推荐实现

    一.单例模式的C#实现: (1)使用double-checked locking的方式: public sealed class Singleton { private static volatile ...

  2. [CSS]Input标签与图片按钮对齐

    页面直接摆放一个input文本框与ImageButton图片按钮,但是发现没有对齐: <input type="text" id="txtQty" /&g ...

  3. 【淘淘】Quartz作业存储与管理

    一.Quartz作业管理和存储方式简介: 作业一旦被调度,调度器需要记住并且跟踪作业和它们的执行次数.如果你的作业是30分钟后或每30秒调用,这不是很有用.事实上,作业执行需要非常准确和即时调用在被调 ...

  4. Intent传递list<bean>集合

    首先你定义的bean需要继承Serializable接口 //传递list<bean>集合Intent intent = new Intent(ViolationOfTheQueryAct ...

  5. C# 五、谈扩展方法的理解

    http://www.cnblogs.com/zhaopei/p/5678842.html

  6. Nagios配置文件详解

    首先要看看目前Nagios的主配置路径下有哪些文件.[root@nagios etc]# ll总用量 152-rwxrwxr-x. 1 nagios nagios 1825 9月  24 14:40 ...

  7. nginx中配置pathinfo模式示例

    要想让nginx支持PATH_INFO,首先需要知道什么是pathinfo,为什么要用pathinfo? pathinfo不是nginx的功能,pathinfo是php的功能. php中有两个path ...

  8. 用于异步的BackgroundWorker

    XAML代码: <Window x:Class="backgroundtest.MainWindow" xmlns="http://schemas.microsof ...

  9. dede调用img图片

    1.默认的index.htm调用: {dede:arclist row='3' titlelen='30' typeid='1'} <div class="swiper-slide&q ...

  10. Python In Action:二、 最小的GUI程序:麻雀虽小,五脏俱全

    Python in Action第二个例子,倒是很简单,却是最基本的GUI程序框架,里面有最基本的实现GUI流程 import wx class MyApp(wx.App): def OnInit(s ...