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})
时间: 2024-10-25 17:48:56

simple_tag,filte,分页以及cookie和装饰器的相关文章

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

一.使用Django自带的decorator 通常情况,使用 函数定义的view,可以直接使用 login_required 直接装饰 @login_required def index(request): if request.method == "GET": return render(request, "index.htm") def user_login(request): if request.method == "GET": retu

Django基于Cookie装饰器实现用户认证

def login(request): if request.method =="GET": return render(request,"login.html") elif request.method == "POST": u = request.POST.get("user") p = request.POST.get("password") print(u,p) if u ==user and p

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

本节知识点概要 1.URL 2.views - 请求其他信息 - 装饰器 3.Templates - 母版 - 自定义 4.Models操作 5.分页(自定义分页) 6.cookie 7.session 8.Form验证 - 缓存 - 中间件 - 信号 - CSRF - Admin/ModelForm 上节内容回顾 1.请求周期 url> 路由 > 函数或类 > 返回字符串或者模板语言? form表单提交 提交 -> url路由系统 > 函数或类中的方法 - 执行其他操作,最

生成器,装饰器之类

前期知识点回顾 内容回顾1.可迭代对象.迭代器.生成器.装饰器有什么区别? 可迭代对象:内部实现了__iter__方法,是一个迭代器 迭代器:内部实现了__iter__和__next__方法,可以进行for循环 生成器:函数内部有yield的就是生成器,生成器也有一个__next__方法,它的本质是一个迭代器. 生成器有两大功能:1.生成 2.迭代 装饰器:在函数执行之前或者函数执行之后要扩展的功能,装饰器是用闭包实现的2.面向对象的方法?面向对象有三种方法: 实例方法:def func(sel

python day4笔记 常用内置函数与装饰器

1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any             判断迭代器中的数据是否有一个为真,有返回真,可迭代数据为空或者没有真,返回假 bin             转换整数为二进制字符串 hex            转换整数为十六进制字符串 oct             转换整数为八进制字符串 bool           转换数据为布尔值

python-day04 内置函数和函数装饰器

python内置函数 1.数学相关 abs(x) 取x绝对值 divmode(x,y) 取x除以y的商和余数,常用做分页,返回商和余数组成一个元组 pow(x,y[,z]) 取x的y次方 ,等同于x ** y,如果给出z值,该函数就计算x的y次幂值被z取模的值 round(x,[,n]) 四舍五入取x的值,n表示取小数点几位 min(X) 取X中最小的值 max(X) 取X中最大值 练习举例: >>> abs(-10) #取-10的绝对值 10 >>> abs(10)

Python学习之旅 —— 基础篇(四)内置函数、装饰器

本篇要点: 内置函数 装饰器 一.内置函数 # abs() :取绝对值 >>> res = abs(-10) >>> print(res) 10 # 0,None,"",{},[],() 布尔值都为空 # all(),any() 判断值的真假 # all() 所有为真才为真 p = all([0,1,2,3]) # 0为False,所有p 是False print(p) # any() 任意一个为真即为真 p = any((0,""

函数+装饰器+迭代器+生成器

闭包函数 闭包:定义在内网函数,包含对外部作用域而非全局作用域 范围:一个函数套用1或n个函数 from urllib.request import urlopen #urlopen模块 作用:爬网页 #闭包函数,内部get函数调用外部page函数 def page(url): #调用url def get(): #下载 return urlopen(url).read() #爬网页 return get #返回url值 baidu=page("http://www.baidu.com"

python学习之路-4 内置函数和装饰器

本篇涉及内容 内置函数 装饰器 内置函数 callable()   判断对象是否可以被调用,返回一个布尔值 1 2 3 4 5 6 7 8 9 10 11 num = 10 print(callable(num))   # num不能够被调用,返回False    def f1():     print("name")    print(callable(f1))     # f1可以被调用,返回True    # 输出 False True ?chr()   将十进制整数转换为asc