加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Django进阶

发布时间:2020-12-15 17:17:07 所属栏目:大数据 来源:网络整理
导读:?内容简介: cookie介绍 session介绍 分页 CSRF 中间件 缓存 信号 一、cookie介绍 ?1、cookie机制 ,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这

?内容简介:

  • cookie介绍
  • session介绍
  • 分页
  • CSRF
  • 中间件
  • 缓存
  • 信号
一、cookie介绍?1、cookie机制

,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。

。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。

由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。

  • ?获取cookie
说明:request.COOKIES
request.COOKIES[]    
request.COOKIES.get() 
  • 设置cookie
=render(request,=redirect( ,value) response.set_signed_cookie(key,value,salt=,...) ===None,cookie失效时间戳(IE requires expires,so set it hasn path=,Cookie生效的路径,/===False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖
  • 带签名的cookie:设置时候加签,cookie内容是加密的
response.set_signed_cookie(,,salt=<span style="color: #008000;">#<span style="color: #008000;">从请求中获取cookie,salt参数要一致
request.get_signed_cookie(<span style="color: #800000;">'
<span style="color: #800000;">username
<span style="color: #800000;">'
,salt=<span style="color: #800000;">'
<span style="color: #800000;">adada
<span style="color: #800000;">'
)

  • 使用javascript操作cookie,前提不能设置httponly=True(使用js,需要下载引人jquery.cookie.js插件)
  • 示例代码一:使用cookies做用户认证
request.method===request.COOKIES.get() redirect( render(request,,{<span style="color: #0000ff;">def<span style="color: #000000;"> login(request):
<span style="color: #0000ff;">if
request.method==<span style="color: #800000;">"
<span style="color: #800000;">GET
<span style="color: #800000;">"
<span style="color: #000000;">:
<span style="color: #0000ff;">return
render(request,<span style="color: #800000;">'
<span style="color: #800000;">login.html
<span style="color: #800000;">'
<span style="color: #000000;">)
<span style="color: #0000ff;">if
request.method==<span style="color: #800000;">"
<span style="color: #800000;">POST
<span style="color: #800000;">"
<span style="color: #000000;">:
u
=request.POST.get(<span style="color: #800000;">'
<span style="color: #800000;">user
<span style="color: #800000;">'
<span style="color: #000000;">)
p
=request.POST.get(<span style="color: #800000;">'
<span style="color: #800000;">pwd
<span style="color: #800000;">'
<span style="color: #000000;">)
<span style="color: #0000ff;">print
<span style="color: #000000;">(u,p)
<span style="color: #0000ff;">if
u==<span style="color: #800000;">'
<span style="color: #800000;">admin<span style="color: #800000;">' <span style="color: #0000ff;">and p==<span style="color: #800000;">'<span style="color: #800000;">admin<span style="color: #800000;">'<span style="color: #000000;">:
response=redirect(<span style="color: #800000;">'<span style="color: #800000;">/app01/index/<span style="color: #800000;">'<span style="color: #000000;">)
<span style="color: #008000;">#<span style="color: #008000;">response.set_cookie('username',u,max_age=60*60)#设置一个小时以后cookie失效
<span style="color: #0000ff;">import<span style="color: #000000;"> datetime
current_date=<span style="color: #000000;">datetime.datetime.now()
expre_date=current_date+datetime.timedelta(seconds=5<span style="color: #000000;">)
response.set_cookie(<span style="color: #800000;">'<span style="color: #800000;">username<span style="color: #800000;">',expires=expre_date) <span style="color: #008000;">#<span style="color: #008000;"> 设置5秒后cookie过期
<span style="color: #0000ff;">return<span style="color: #000000;"> response
<span style="color: #0000ff;">else<span style="color: #000000;">:
<span style="color: #0000ff;">return redirect(<span style="color: #800000;">'<span style="color: #800000;">/app01/login/<span style="color: #800000;">')

  • 示例代码二:基于Cookie实现定制显示数据条数(包含juery操作cookie)
    
    

模版代码:

Title {{ row }} 10 30 50 100 })

<span style="color: #0000ff;"></<span style="color: #800000;">script<span style="color: #0000ff;">>
<span style="color: #0000ff;"></<span style="color: #800000;">body<span style="color: #0000ff;">>
<span style="color: #0000ff;"></<span style="color: #800000;">html<span style="color: #0000ff;">>

视图代码:

.utils request.method=== int(request.GET.get(,1)) page_num=request.COOKIES.get(== page.PagiNation(current_index=current_index,data_num=500,page_num==mypage.page_str(= render(request,,{:data,:page_str})

基础篇中的django视图提到了,对于view函数中我们可以定义两种视图,一种是函数(FBV),一种是类(CBV)

所以对于认证的装饰器也有两种:

  • FBV
inner(reqeust,*args,**= reqeust.COOKIES.get( redirect( func(reqeust,**<span style="color: #008000;">#<span style="color: #008000;">装饰需要登录验证的函数
<span style="color: #000000;">@auth
<span style="color: #0000ff;">def
<span style="color: #000000;"> index(reqeust):
<span style="color: #0000ff;">return
render(reqeust,{<span style="color: #800000;">'
<span style="color: #800000;">current_user
<span style="color: #800000;">'
: v})

  • CBV
inner(reqeust,**<span style="color: #008000;">#<span style="color: #008000;">使用装饰器,方法有三种

<span style="color: #0000ff;">from django <span style="color: #0000ff;">import<span style="color: #000000;"> views
<span style="color: #0000ff;">from django.utils.decorators <span style="color: #0000ff;">import<span style="color: #000000;"> method_decorator

@method_decorator(auth,name=<span style="color: #800000;">'<span style="color: #800000;">dispatch<span style="color: #800000;">'<span style="color: #000000;">)
<span style="color: #008000;">#<span style="color: #008000;"> 第三种方法,name="dispatch",就是给dispatch方法加上此装饰器,作用在于在执行post、get方法之前就验证,避免在给post和get方法加装饰器
<span style="color: #0000ff;">class<span style="color: #000000;"> Order(views.View):

<span style="color: #008000;">#<span style="color: #008000;"> @method_decorator(auth) # 第二种方法,作用等同于等三种
<span style="color: #008000;">#<span style="color: #008000;"> def dispatch(self,request,kwargs):
<span style="color: #008000;">#<span style="color: #008000;"> return super(Order,self).dispatch(request,
kwargs)

<span style="color: #008000;">#<span style="color: #008000;"> @method_decorator(auth) # 第一种方法,作用可以用针对性,可以只给get方法加装饰器
<span style="color: #0000ff;">def<span style="color: #000000;"> get(self,reqeust):<span style="color: #0000ff;">return render(reqeust,{<span style="color: #800000;">'<span style="color: #800000;">current_user<span style="color: #800000;">'<span style="color: #000000;">: v})

<span style="color: #0000ff;">def<span style="color: #000000;"> post(self,{<span style="color: #800000;">'<span style="color: #800000;">current_user<span style="color: #800000;">': v})

<table style="height: 30px; background-color: #afeeee; width: 1266px; ; width: 1266px;" border="0">

<tr>
<td><span style="font-size: 16px;">二、session介绍</td>
</tr></table>

?1、session机制

除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。,使用上比Cookie简单一些,相应的也

2、session工作原理

?3、Django中使用session

  • 基本操作
request.session[] request.session[]

<span style="color: #008000;">#<span style="color: #008000;">设置session
request.session[<span style="color: #800000;">'<span style="color: #800000;">k1<span style="color: #800000;">']=<span style="color: #800000;">'<span style="color: #800000;">wd<span style="color: #800000;">'<span style="color: #000000;">
request.session.setdefault(<span style="color: #800000;">'<span style="color: #800000;">key<span style="color: #800000;">',<span style="color: #800000;">'<span style="color: #800000;">value<span style="color: #800000;">') <span style="color: #008000;">#<span style="color: #008000;">存在则不设置

<span style="color: #008000;">#<span style="color: #008000;">删除某个session键值
<span style="color: #0000ff;">del request.session[<span style="color: #800000;">'<span style="color: #800000;">key<span style="color: #800000;">'<span style="color: #000000;">]

<span style="color: #008000;">#<span style="color: #008000;">循环session中的字典,与字典循环类似
request.session.keys() <span style="color: #008000;">#<span style="color: #008000;">所有的key
request.session.values() <span style="color: #008000;">#<span style="color: #008000;">所有的value
request.session.items() <span style="color: #008000;">#<span style="color: #008000;">k,v形式
request.session.iterkeys() <span style="color: #008000;">#<span style="color: #008000;">所有的key
request.session.itervalues() <span style="color: #008000;">#<span style="color: #008000;">所有的value
request.session.iteritems() <span style="color: #008000;">#<span style="color: #008000;">k,v形式

<span style="color: #008000;">#<span style="color: #008000;">获取用户session中的随机字符串
<span style="color: #000000;">request.session.session_key

<span style="color: #008000;">#<span style="color: #008000;">删除所有session失效日期小于当前日志的数据(删除同一用户制造的脏数据)
<span style="color: #000000;">request.session.clear_expired()

<span style="color: #008000;">#<span style="color: #008000;">删除当前用户的所有session数据(在用户退出登录时候使用)
request.session.delete(<span style="color: #800000;">'<span style="color: #800000;">用户随机字符串<span style="color: #800000;">')<span style="color: #008000;">#<span style="color: #008000;">使用比较麻烦,因为还的获取用户随机字符串
request.session.clear()<span style="color: #008000;">#<span style="color: #008000;">该方法会先获取用户的随机字符串,然后把其对应的所有数据删除,推荐注销(退出登录)时候使用<span style="color: #008000;">

<span style="color: #008000;">设置seesion失效时间

<span style="color: #000000;">request.session.set_expiry(value)
<span style="color: #000000;"> 如果value是个整数,session会在些秒数后失效。
<span style="color: #000000;"> 如果value是个datatime或timedelta,session就会在这个时间后失效。
<span style="color: #000000;"> 如果value是0,用户关闭浏览器session就会失效。
如果value是None,session会依赖全局session失效策略,默认全局两周失效

?4、Django中session相关配置

django默认session存储位置在数据库表中,表名为django_session,当然django还提供了多样化存储session,有以下几种:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

1、数据库Session配置

SESSION_ENGINE </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.contrib.sessions.backends.db</span><span style="color: #800000;"&gt;'</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 引擎(默认)</span>

<span style="color: #000000;">
SESSION_COOKIE_NAME = <span style="color: #800000;">"<span style="color: #800000;">sessionid<span style="color: #800000;">" <span style="color: #008000;">#<span style="color: #008000;"> Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认
SESSION_COOKIE_PATH = <span style="color: #800000;">"<span style="color: #800000;">/<span style="color: #800000;">" <span style="color: #008000;">#<span style="color: #008000;"> Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None <span style="color: #008000;">#<span style="color: #008000;"> Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False <span style="color: #008000;">#<span style="color: #008000;"> 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True <span style="color: #008000;">#<span style="color: #008000;"> 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 <span style="color: #008000;">#<span style="color: #008000;"> Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False <span style="color: #008000;">#<span style="color: #008000;"> 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False <span style="color: #008000;">#<span style="color: #008000;"> 是否每次请求都保存Session,默认修改之后才保存(默认),最好设置为True,这样超时时间都是最新的

2、缓存session(memchache)配置

SESSION_ENGINE </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.contrib.sessions.backends.cache</span><span style="color: #800000;"&gt;'</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 引擎</span> SESSION_CACHE_ALIAS = <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置</span>

<span style="color: #000000;">

SESSION_COOKIE_NAME = </span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;sessionid</span><span style="color: #800000;"&gt;"</span>                        <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串</span>
SESSION_COOKIE_PATH = <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;/</span><span style="color: #800000;"&gt;"</span>                                <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; Session的cookie保存的路径</span>
SESSION_COOKIE_DOMAIN = None                              <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; Session的cookie保存的域名</span>
SESSION_COOKIE_SECURE = False                             <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 是否Https传输cookie</span>
SESSION_COOKIE_HTTPONLY = True                            <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 是否Session的cookie只支持http传输</span>
SESSION_COOKIE_AGE = 1209600                              <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; Session的cookie失效日期(2周)</span>
SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 是否关闭浏览器使得Session过期</span>
SESSION_SAVE_EVERY_REQUEST = False                        <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 是否每次请求都保存Session,默认修改之后才保存</span></pre>

3、文件session配置

SESSION_ENGINE </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.contrib.sessions.backends.file</span><span style="color: #800000;"&gt;'</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 引擎</span> SESSION_FILE_PATH = None <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T</span>

4、数据库+缓存session配置

4、缓存+a. 配置 settings.py

SESSION_ENGINE </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.contrib.sessions.backends.cached_db</span><span style="color: #800000;"&gt;'</span>        <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 引擎</span></pre>

5、加密cookie session配置

SESSION_ENGINE </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.contrib.sessions.backends.signed_cookies</span><span style="color: #800000;"&gt;'</span> <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 引擎</span></pre>

5、基于session的用户验证装饰器

wrap(request,** request.session.get( redirect( func(request,** wrap

?6、session和cookie区别

1.作用

当你要登录京东和天猫的时候,当登录成功的时候。我点击其他功能例如购物车 订单等功能的时候是如何判断你已经登录的呢。那就是用的cookie或者session功能。

2.区别

cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,

4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

3.session流程

1、自动生成一段字符串

2、将字符串发送到客户端的浏览器,同时把字符串当做key放在session里。(可以理解为session就是一个字典)

3、在用户的session对应的value里设置任意值

<table style="height: 30px; background-color: #afeeee; width: 1266px; ; width: 1266px;" border="0">

<tr>
<td><span style="font-size: 16px;">三、分页</td>

</tr>

</table>

一、Django自带的分页

视图:

django.shortcuts django.core.paginator L =<span style="color: #000000;"> []
<span style="color: #0000ff;">for
i <span style="color: #0000ff;">in
range(999<span style="color: #000000;">):
L.append(i)

<span style="color: #0000ff;">def<span style="color: #000000;"> index(request):
current_page = request.GET.get(<span style="color: #800000;">'<span style="color: #800000;">p<span style="color: #800000;">'<span style="color: #000000;">)

paginator </span>= Paginator(L,10<span style="color: #000000;"&gt;)
</span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; per_page: 每页显示条目数量</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; count:    数据总个数</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; num_pages:总页数</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; page_range:总页数的索引范围,如: (1,10),(1,200)</span>
<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; page:     page对象</span>
<span style="color: #0000ff;"&gt;try</span><span style="color: #000000;"&gt;:
    posts </span>=<span style="color: #000000;"&gt; paginator.page(current_page)
    </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; has_next              是否有下一页</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; next_page_number      下一页页码</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; has_previous          是否有上一页</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; previous_page_number  上一页页码</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; object_list           分页之后的数据列表</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; number                当前页</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; paginator             paginator对象</span>
<span style="color: #0000ff;"&gt;except</span><span style="color: #000000;"&gt; PageNotAnInteger:
    posts </span>= paginator.page(1<span style="color: #000000;"&gt;)
</span><span style="color: #0000ff;"&gt;except</span><span style="color: #000000;"&gt; EmptyPage:
    posts </span>=<span style="color: #000000;"&gt; paginator.page(paginator.num_pages)
</span><span style="color: #0000ff;"&gt;return</span> render(request,{<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;posts</span><span style="color: #800000;"&gt;'</span>: posts})</pre>

模版文件

> >
    % item posts %
  • {{ item }}
  • % endfor %

<div <span style="color: #0000ff;">class=<span style="color: #800000;">"<span style="color: #800000;">pagination<span style="color: #800000;">">
<span <span style="color: #0000ff;">class=<span style="color: #800000;">"<span style="color: #800000;">step-links<span style="color: #800000;">"><span style="color: #000000;">
{% <span style="color: #0000ff;">if posts.has_previous %<span style="color: #000000;">}
<a href=<span style="color: #800000;">"<span style="color: #800000;">?p={{ posts.previous_page_number }}<span style="color: #800000;">">Previous<span style="color: #000000;">
{% endif %<span style="color: #000000;">}
<span <span style="color: #0000ff;">class=<span style="color: #800000;">"<span style="color: #800000;">current<span style="color: #800000;">"><span style="color: #000000;">
Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
<span style="color: #000000;">
{% <span style="color: #0000ff;">if posts.has_next %<span style="color: #000000;">}
<a href=<span style="color: #800000;">"<span style="color: #800000;">?p={{ posts.next_page_number }}<span style="color: #800000;">">Next<span style="color: #000000;">
{% endif %<span style="color: #000000;">}

扩展内置分页:

django.shortcuts django.core.paginator <span style="color: #0000ff;">class<span style="color: #000000;"> CustomPaginator(Paginator):
<span style="color: #0000ff;">def
<span style="color: #800080;">init
(self,current_page,max_pager_num,*<span style="color: #000000;">kwargs):
<span style="color: #800000;">"""<span style="color: #800000;">
:param current_page: 当前页
:param max_pager_num:最多显示的页码个数
:param args:
:param kwargs:
:return:
<span style="color: #800000;">"""<span style="color: #000000;">
self.current_page =<span style="color: #000000;"> int(current_page)
self.max_pager_num =<span style="color: #000000;"> max_pager_num
super(CustomPaginator,self).<span style="color: #800080;">init(
args,**<span style="color: #000000;">kwargs)

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; page_num_range(self):
    </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 当前页面</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; self.current_page</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 总页数</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; self.num_pages</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 最多显示的页码个数</span>
    <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; self.max_pager_num</span>
    <span style="color: #0000ff;"&gt;print</span>(1<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;if</span> self.num_pages <<span style="color: #000000;"&gt; self.max_pager_num:
        </span><span style="color: #0000ff;"&gt;return</span> range(1,self.num_pages + 1<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;print</span>(2<span style="color: #000000;"&gt;)
    part </span>= int(self.max_pager_num / 2<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;if</span> self.current_page - part < 1<span style="color: #000000;"&gt;:
        </span><span style="color: #0000ff;"&gt;return</span> range(1,self.max_pager_num + 1<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;print</span>(3<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;if</span> self.current_page + part ><span style="color: #000000;"&gt; self.num_pages:
        </span><span style="color: #0000ff;"&gt;return</span> range(self.num_pages + 1 - self.max_pager_num,self.num_pages + 1<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;print</span>(4<span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;return</span> range(self.current_page - part,self.current_page + part + 1<span style="color: #000000;"&gt;)

L =<span style="color: #000000;"> []
<span style="color: #0000ff;">for i <span style="color: #0000ff;">in range(999<span style="color: #000000;">):
L.append(i)

<span style="color: #0000ff;">def<span style="color: #000000;"> index(request):
current_page = request.GET.get(<span style="color: #800000;">'<span style="color: #800000;">p<span style="color: #800000;">'<span style="color: #000000;">)
paginator = CustomPaginator(current_page,11,L,200)
<span style="color: #008000;">#<span style="color: #008000;"> page: page对象
<span style="color: #0000ff;">try<span style="color: #000000;">:
posts =<span style="color: #000000;"> paginator.page(current_page)
<span style="color: #008000;">#<span style="color: #008000;"> has_next 是否有下一页
<span style="color: #008000;">#<span style="color: #008000;"> next_page_number 下一页页码
<span style="color: #008000;">#<span style="color: #008000;"> has_previous 是否有上一页
<span style="color: #008000;">#<span style="color: #008000;"> previous_page_number 上一页页码
<span style="color: #008000;">#<span style="color: #008000;"> object_list 分页之后的数据列表
<span style="color: #008000;">#<span style="color: #008000;"> number 当前页
<span style="color: #008000;">#<span style="color: #008000;"> paginator paginator对象
<span style="color: #0000ff;">except<span style="color: #000000;"> PageNotAnInteger:
posts = paginator.page(1<span style="color: #000000;">)
<span style="color: #0000ff;">except<span style="color: #000000;"> EmptyPage:
posts =<span style="color: #000000;"> paginator.page(paginator.num_pages)

</span><span style="color: #0000ff;"&gt;return</span> render(request,{<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;posts</span><span style="color: #800000;"&gt;'</span>: posts})</pre>
> >
    % item posts %
  • {{ item }}
  • % endfor %

<div <span style="color: #0000ff;">class=<span style="color: #800000;">"<span style="color: #800000;">pagination<span style="color: #800000;">">
<span <span style="color: #0000ff;">class=<span style="color: #800000;">"<span style="color: #800000;">step-links<span style="color: #800000;">"><span style="color: #000000;">
{% <span style="color: #0000ff;">if posts.has_previous %<span style="color: #000000;">}
<a href=<span style="color: #800000;">"<span style="color: #800000;">?p={{ posts.previous_page_number }}<span style="color: #800000;">">Previous<span style="color: #000000;">
{% endif %<span style="color: #000000;">}

{</span>% <span style="color: #0000ff;"&gt;for</span> i <span style="color: #0000ff;"&gt;in</span> posts.paginator.page_num_range %<span style="color: #000000;"&gt;}
    </span><a href=<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;?p={{ i }}</span><span style="color: #800000;"&gt;"</span>>{{ i }}</a><span style="color: #000000;"&gt;
{</span>% endfor %<span style="color: #000000;"&gt;}

{</span>% <span style="color: #0000ff;"&gt;if</span> posts.has_next %<span style="color: #000000;"&gt;}
    </span><a href=<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;?p={{ posts.next_page_number }}</span><span style="color: #800000;"&gt;"</span>>Next</a><span style="color: #000000;"&gt;
{</span>% endif %<span style="color: #000000;"&gt;}

<span <span style="color: #0000ff;">class=<span style="color: #800000;">"<span style="color: #800000;">current<span style="color: #800000;">"><span style="color: #000000;">
Page {{ posts.number }} of {{ posts.paginator.num_pages }}.

二、自定义分页

先介绍下XSS(跨站脚本攻击):

跨站脚本攻击(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。

原因:我们在自定义分页时候会额外的给页面添加html代码,默认Django会认为这些代码是不安全的属于XSS攻击,所以会当作字符串处理不会作为html代码显示,所以我们需要告诉Django这个代码是安全的。

方法有两种:

1.在html模板中方法:

{{ html_str|safe }}

2.在后台函数中使用

django.utils.safestring =mark_safe(html_str)

?3.自定义分页(可以作为一个工具类,作为公共模块使用)

django.utils.safestring (self,current_index,data_num,page_num=10,show_index_num=10==== start(self): (self.current_index - 1) * end(self): self.current_index * total_index(self): math.ceil(self.data_num /</span><span style="color: #0000ff;"&gt;def</span> page_str(self,base_url): <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;获取最后展现的a标签字符串</span> <span style="color: #800000;"&gt;'''</span><span style="color: #800000;"&gt; :param base_url: 跳转链接地址 :return: 返回django认可的html代码 </span><span style="color: #800000;"&gt;'''</span><span style="color: #000000;"&gt; page_list</span>=<span style="color: #000000;"&gt;[] half_index </span>= int(self.show_index_num/2) <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 显示页码数的一半</span> <span style="color: #0000ff;"&gt;if</span> self.total_index < self.show_index_num: <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 起始页码小于显示的页码数目,结束页码则为总显示页数</span> start_index = 1<span style="color: #000000;"&gt; end_index </span>= self.total_index+1 <span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: </span><span style="color: #0000ff;"&gt;if</span> self.current_index < half_index <span style="color: #0000ff;"&gt;or</span> self.current_index == half_index:<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;当前页码小于或等于显示页码数量的一半</span> start_index = 1<span style="color: #000000;"&gt; end_index </span>= self.show_index_num + 1 <span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: start_index </span>= self.current_index - half_index + 1 <span style="color: #0000ff;"&gt;if</span> self.current_index + half_index > self.total_index:<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;当前页码+显示页码数的一半大于总的页码数目</span> start_index = self.total_index - self.show_index_num + 1<span style="color: #000000;"&gt; end_index </span>= self.total_index + 1 <span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: end_index </span>= self.current_index + half_index + 1 <span style="color: #0000ff;"&gt;if</span> self.current_index == 1<span style="color: #000000;"&gt;: page_list.append(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a class="pg-a" href="javascript:void(0);"&gt;上一页</a></span><span style="color: #800000;"&gt;'</span>)<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;javascript:void(0)意思是不错任何操作</span> <span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: page_list.append(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a href=%s?p=%s class="pg-a alive"&gt;上一页</a></span><span style="color: #800000;"&gt;'</span> % (base_url,self.current_index - 1<span style="color: #000000;"&gt;,)) </span><span style="color: #0000ff;"&gt;for</span> i <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; range(start_index,end_index): </span><span style="color: #0000ff;"&gt;if</span> i ==<span style="color: #000000;"&gt; self.current_index: page_url </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a href=%s?p=%s class="pg-a alive"&gt;%s</a></span><span style="color: #800000;"&gt;'</span> %<span style="color: #000000;"&gt; (base_url,i,i) </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: page_url </span>= <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a href=%s?p=%s class="pg-a "&gt;%s</a></span><span style="color: #800000;"&gt;'</span> %<span style="color: #000000;"&gt; (base_url,i) page_list.append(page_url) </span><span style="color: #0000ff;"&gt;if</span> self.current_index ==<span style="color: #000000;"&gt; self.total_index: page_list.append(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a class="pg-a" href="javascript:void(0);"&gt;下一页</a></span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;) </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: page_list.append(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;<a href=%s?p=%s class="pg-a alive"&gt;下一页</a></span><span style="color: #800000;"&gt;'</span> % (base_url,self.current_index + 1<span style="color: #000000;"&gt;,)) page_str </span>= mark_safe(<span style="color: #800000;"&gt;""</span><span style="color: #000000;"&gt;.join(page_list)) </span><span style="color: #0000ff;"&gt;return</span> page_str</pre>

4.使用示例

.utils request.method=== int(request.GET.get(,1)) mypage = page.PagiNation(current_index=current_index,data_num=500=mypage.page_str( render(request,:page_str})

<table style="height: 30px; background-color: #afeeee; width: 1266px; ; width: 1266px;" border="0">

<tr>
<td><span style="font-size: 16px;">四、跨站请求伪造(CSRF)</td>
</tr>
</table>

?1、简介:

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比更具危险性。

2、Django中防护CSRF模块

Django中的CSRF防护是通过中间件的手段来达到防护的目的,中间件路径:django.middleware.csrf.CsrfViewMiddleware ,配置文件settings中指定了全局配置,单也可以单独针对某个views函数来配置,具体配置:

中间件 django.middleware.csrf.CsrfViewMiddleware

@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

TIPS:配置模块导入from django.views.decorators.csrf import csrf_exempt,csrf_protect

?3、原理

当我们向Django后台post数据时,在Django中防护CSRF是通过获取用户请求头中是否含有X-CSRFtoken请求头所对应的随机字符串(),如果有并且是正确的,则可以提交,否则则返回Forbidden(403)错误。

4、提交数据

form表单提交数据:在form表单中加上{% csrf_token %},默认会在表单中生成隐藏的input标签

提交过程:

用户访问页面,{% csrf_token %}模版语言生成CSRF随机随机字符串,并且cookie中也生成了该字符串,当用户提交数据时候cookie中会带着这个字符串进行提交,如果没有该字符串则提交失败

通过ajax提交数据时候,和form表单一样,我们提交数据时需要在请求头中加上X-CSRFtoken,所以提交的时候需要利用js获取cookie中的该随机字符串进行提交:

$("#btn").click("/login/""POST""user":"wd","pwd":"1234""X-CSRFtoken":$.cookie("csrftoken")}, success: } }) })</span></pre>

但是如果页面中有多个ajax请求的话就在每个ajax中添加headers信息,所以可以在页面框架加载完时候通过以下方式提交,这样会在页面中所有ajax提交数据之前加上csrftoken信息

xhr.setRequestHeader("X-CSRFtoken",$.cookie("csrftoken"

最后,一般我们只希望post提交数据时候才会使用csrf验证,所以官网推荐

(/^(GET|HEAD|OPTIONS|TRACE)$/ } $.ajaxSetup({ beforeSend: (!csrfSafeMethod(settings.type) && !"X-CSRFToken"

5、Django后台验证过程

csrf在前端的key为X-CSRFtoken,通过form或者ajax提交到后台,后端的django会自动添加HTTP_,并且最后为的key变成HTTP_X_CSRFtoken,如果随机字符串通过验证则数据提交,否则报错(403)。

五、Django中间件?1、简介

django中的中间件,在其他web框架中,有的叫管道或者httphandle,Django中很多功能都是通过中间件实现的,实际上中间件就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。在工程中的settings.py中由变量MIDDLEWARE控制,请求从上到下依次穿过中间件,每个中间件中都可以有5个方法:

  • process_request(self,request)#请求最开始执行的方法
  • process_response(self,response)#请求返回时候执行的方法
  • process_view(self,callback,callback_args,callback_kwargs)#请求到达views视图之前执行的方法
  • process_exception(self,exception) ?# 默认不执行,除非Views方法出错
  • process_template_response(self,response) ? # 默认不执行,除非Views中的函数返回的对象中,具有render方法(区别于模板渲染的render)

2、请求在中间件中的方法请求过程

  1. 用户请求先中间件,由上到下先后执行每个中间件process_request方法;
  2. 执行完每个中间件的process_request方法之后,请求到达urls路由关系映射;
  3. 到达urls路由映射以后,由下至上执行每个中间件的process_views方法;
  4. 执行完process_views,请求到达views函数,此时若views函数有错误信息,则由下到上执行process_exception方法,直到错误被抓住停止,都没有抓住页面包错;
  5. 如果views函数中没有出错,那么请求由下到上执行每个中间件的process_response方法,最后响应客户;

大致的请求过程:

?3、自定义中间件

自定义中间件,我们至少包括两个方法,一个是process_request,还有一个是process_response,创建一个py文件,在工程中创建MyMiddleWare目录(与tempates同级),创建文件md.py,注意使用process_response必须返回response:

django.utils.deprecation django.shortcuts <span style="color: #008000;">#<span style="color: #008000;">中间件1
<span style="color: #0000ff;">class
<span style="color: #000000;"> Row1(MiddlewareMixin):
<span style="color: #0000ff;">def
<span style="color: #000000;"> process_request(self,request):
<span style="color: #0000ff;">print
(<span style="color: #800000;">"<span style="color: #800000;">中间件1请求<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">def<span style="color: #000000;"> process_response(self,response):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件1返回<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">return<span style="color: #000000;"> response

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; process_view(self,callback_kwargs):
    </span><span style="color: #0000ff;"&gt;print</span>(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;中间件1view</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)

<span style="color: #008000;">#<span style="color: #008000;">中间件2
<span style="color: #0000ff;">class<span style="color: #000000;"> Row2(MiddlewareMixin):
<span style="color: #0000ff;">def<span style="color: #000000;"> process_request(self,request):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件2请求<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #008000;">#<span style="color: #008000;"> return HttpResponse("走")
<span style="color: #0000ff;">def<span style="color: #000000;"> process_response(self,response):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件2返回<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">return<span style="color: #000000;"> response
<span style="color: #0000ff;">def<span style="color: #000000;"> process_view(self,callback_kwargs):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件2view<span style="color: #800000;">"<span style="color: #000000;">)

<span style="color: #008000;">#<span style="color: #008000;">中间件3
<span style="color: #0000ff;">class<span style="color: #000000;"> Row3(MiddlewareMixin):
<span style="color: #0000ff;">def<span style="color: #000000;"> process_request(self,request):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件3请求<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">def<span style="color: #000000;"> process_response(self,response):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件3返回<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">return<span style="color: #000000;"> response
<span style="color: #0000ff;">def<span style="color: #000000;"> process_view(self,callback_kwargs):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">中间件3view<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">def<span style="color: #000000;"> process_exception(self,exception):
<span style="color: #800000;">"""<span style="color: #800000;">只有出现异常时才会执行<span style="color: #800000;">"""
<span style="color: #0000ff;">if<span style="color: #000000;"> isinstance(exception,ValueError):
<span style="color: #0000ff;">return HttpResponse(<span style="color: #800000;">'<span style="color: #800000;">出现异常》。。<span style="color: #800000;">'<span style="color: #000000;">)
<span style="color: #0000ff;">elif<span style="color: #000000;"> isinstance(exception,TemplateDoesNotExist):
<span style="color: #0000ff;">print<span style="color: #000000;">(request.path_info)
<span style="color: #0000ff;">return render(request,<span style="color: #800000;">"<span style="color: #800000;">404.html<span style="color: #800000;">"<span style="color: #000000;">)

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; process_template_response(self,response):
    </span><span style="color: #800000;"&gt;"""</span><span style="color: #800000;"&gt;如果Views中的函数返回的对象中,具有render方法才会执行</span><span style="color: #800000;"&gt;"""</span>
    <span style="color: #0000ff;"&gt;print</span>(<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;-----------------------</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;return</span> response</pre>

注册中间件:使用中间件需要在settings.py中注册你的中间件,配置就是你的中间件文件路径

MIDDLEWARE =

4、版本变化

上面所说的Django中间件请求过程是在1.10版本之后(包括1.10),而在1.10版本之前稍微有些区别,区别就在请求异常时候,

六、缓存?简介

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者memchazhe中之前缓存的内容拿到,并返回。

Django提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

缓存方式配置

?通用配置

CACHES =: , : 300, : 300, : 3, : , : 1, 函数名 </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 自定义key</span> <span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; default_key_func(key,key_prefix,version): </span><span style="color: #800000;"&gt;"""</span><span style="color: #800000;"&gt; Default function to generate keys. Constructs the key used by all other methods. By default it prepends the `key_prefix'. KEY_FUNCTION can be used to specify an alternate function with custom key making behavior. </span><span style="color: #800000;"&gt;"""</span> <span style="color: #0000ff;"&gt;return</span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;%s:%s:%s</span><span style="color: #800000;"&gt;'</span> %<span style="color: #000000;"&gt; (key_prefix,version,key) </span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; get_key_func(key_func): </span><span style="color: #800000;"&gt;"""</span><span style="color: #800000;"&gt; Function to decide which key function to use. Defaults to ``default_key_func``. </span><span style="color: #800000;"&gt;"""</span> <span style="color: #0000ff;"&gt;if</span> key_func <span style="color: #0000ff;"&gt;is</span> <span style="color: #0000ff;"&gt;not</span><span style="color: #000000;"&gt; None: </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; callable(key_func): </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; key_func </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;: </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; import_string(key_func) </span><span style="color: #0000ff;"&gt;return</span> default_key_func</pre>

使用内存

CACHES =: : </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 注:其他配置同开发调试版本</span></pre>

使用文件

=: :

使用数据库

<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 配置:</span>
    CACHES =<span style="color: #000000;"&gt; {
        </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: {
            </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;BACKEND</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.core.cache.backends.db.DatabaseCache</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;LOCATION</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;my_cache_table</span><span style="color: #800000;"&gt;'</span>,<span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 数据库表</span>

<span style="color: #000000;"> }
}

</span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 注:执行创建表命令 python manage.py createcachetable</span></pre>

使用memcache缓存(python-memcached模块)

=: : CACHES </span>=<span style="color: #000000;"&gt; { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;BACKEND</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.core.cache.backends.memcached.MemcachedCache</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;LOCATION</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;unix:/tmp/memcached.sock</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,} } CACHES </span>=<span style="color: #000000;"&gt; { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;BACKEND</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.core.cache.backends.memcached.MemcachedCache</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;LOCATION</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: [ </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;172.19.26.240:11211</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;172.19.26.242:11211</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,] } }</span></pre>

使用Memcache缓存(pylibmc模块)

=: CACHES </span>=<span style="color: #000000;"&gt; { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;BACKEND</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.core.cache.backends.memcached.PyLibMCCache</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;LOCATION</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;/tmp/memcached.sock</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,} } CACHES </span>=<span style="color: #000000;"&gt; { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;default</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;: { </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;BACKEND</span><span style="color: #800000;"&gt;'</span>: <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.core.cache.backends.memcached.PyLibMCCache</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,] } }</span></pre>

缓存应用

?单独视图缓存

<span style="color: #0000ff;">from django.views.decorators.cache <span style="color: #0000ff;">import<span style="color: #000000;"> cache_page

@cache_page(60 * 15<span style="color: #000000;">)
<span style="color: #0000ff;">def<span style="color: #000000;"> my_view(request):
...

方式二:
<span style="color: #0000ff;">from django.views.decorators.cache <span style="color: #0000ff;">import<span style="color: #000000;"> cache_page

    urlpatterns </span>=<span style="color: #000000;"&gt; [
        url(r</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;^foo/([0-9]{1,2})/$</span><span style="color: #800000;"&gt;'</span>,cache_page(60 * 15<span style="color: #000000;"&gt;)(my_view)),]

即通过装饰器的方式实现,导入模块之后,在需要缓存的函数前加@cache_page(60 15) 6015表示缓存时间是15分钟

局部使用

{</span>% load cache %<span style="color: #000000;"&gt;}

b. 使用缓存

    {</span>% cache 5000 缓存key %<span style="color: #000000;"&gt;}
        缓存内容
    {</span>% endcache %}</pre>

全站缓存

MIDDLEWARE </span>=<span style="color: #000000;"&gt; [ </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.middleware.cache.UpdateCacheMiddleware</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,</span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt; 其他中间件...</span> <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;django.middleware.cache.FetchFromCacheMiddleware</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,] CACHE_MIDDLEWARE_ALIAS </span>= <span style="color: #800000;"&gt;""</span><span style="color: #000000;"&gt; CACHE_MIDDLEWARE_SECONDS </span>= <span style="color: #800000;"&gt;""</span><span style="color: #000000;"&gt; CACHE_MIDDLEWARE_KEY_PREFIX </span>= <span style="color: #800000;"&gt;""</span></pre>

<table style="height: 30px; background-color: #afeeee; width: 1266px; ; width: 1266px;" border="0">

<tr>
<td><span style="font-size: 16px;">七、Django中的信号</td>
</tr>
</table>

简介

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

内置信号

post_init pre_save post_save pre_delete post_delete m2m_changed class_prepared post_migrate Request/ request_finished got_request_exception template_rendered

因为这些信号中并没有注册函数,所以运行时并没有调用触发这些信号

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数

django.core.signals request_finished django.core.signals request_started django.core.signals got_request_exception

<span style="color: #0000ff;">from django.db.models.signals <span style="color: #0000ff;">import class_prepared <span style="color: #008000;">#<span style="color: #008000;"> 程序启动时,检测已注册的app中的modal类,对于每一个类,自动触发
<span style="color: #0000ff;">from django.db.models.signals <span style="color: #0000ff;">import pre_init,post_init <span style="color: #008000;">#<span style="color: #008000;"> 构造方法前和构造方法后
<span style="color: #0000ff;">from django.db.models.signals <span style="color: #0000ff;">import pre_save,post_save <span style="color: #008000;">#<span style="color: #008000;"> 对象保存前和对象保存后
<span style="color: #0000ff;">from django.db.models.signals <span style="color: #0000ff;">import pre_delete,post_delete <span style="color: #008000;">#<span style="color: #008000;"> 对象删除前和对象删除后
<span style="color: #0000ff;">from django.db.models.signals <span style="color: #0000ff;">import m2m_changed <span style="color: #008000;">#<span style="color: #008000;"> 操作第三张表前后
<span style="color: #0000ff;">from django.db.models.signals <span style="color: #0000ff;">import pre_migrate,post_migrate <span style="color: #008000;">#<span style="color: #008000;"> 执行migrate命令前后

<span style="color: #0000ff;">from django.test.signals <span style="color: #0000ff;">import setting_changed <span style="color: #008000;">#<span style="color: #008000;"> 使用test测试修改配置文件时
<span style="color: #0000ff;">from django.test.signals <span style="color: #0000ff;">import template_rendered <span style="color: #008000;">#<span style="color: #008000;"> 使用test测试渲染模板时

<span style="color: #0000ff;">from django.db.backends.signals <span style="color: #0000ff;">import connection_created <span style="color: #008000;">#<span style="color: #008000;"> 创建数据库连接时

<span style="color: #0000ff;">def callback(sender,**<span style="color: #000000;">kwargs):
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">xxoo_callback<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">print<span style="color: #000000;">(sender,kwargs)

xxoo.connect(callback)
<span style="color: #008000;">#<span style="color: #008000;"> xxoo指上述导入的内容#示例

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender,**kwargs):
print("Request finished!")<span style="color: #008000;">########################说明####################

自定义信号

步骤:

  • 定义信号
  • 触发信号
  • 注册信号

示例:

=django.dispatch.Signal(providing_args=[,<span style="color: #008000;">#<span style="color: #008000;">注册信号
<span style="color: #0000ff;">def
callback(sender,**<span style="color: #000000;">kwargs):

</span><span style="color: #0000ff;"&gt;print</span>(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;callback</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)

</span><span style="color: #0000ff;"&gt;print</span><span style="color: #000000;"&gt;(sender,kwargs)

pizza_done.connect(callback)

<span style="color: #008000;">#<span style="color: #008000;">触发信号
<span style="color: #0000ff;">from 路径 <span style="color: #0000ff;">import<span style="color: #000000;"> pizza_done

pizza_done.send(sender=<span style="color: #800000;">'<span style="color: #800000;">seven<span style="color: #800000;">',toppings=123,size=456)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!