Django(五)母版繼承、Cookie、視圖裝飾器等

大綱

1、內容回顧
補充:默認值
補充:命名空間
2、模板語言
一、母版繼承
二、include
三、自定義simple_tag
3、Cookie
Cookie 使用總結
4、視圖
一、獲取用戶請求相關信息以及請求頭
二、CBV和FBV用戶認證裝飾器css

2、模板語言

一、母版繼承

母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}        # 指定繼承母版文件
   {% block title %}{% endblock %}

 

示例:html

urls.pypython

url(r'^model/', views.model),

 

views.pyjquery

def model(request):
    user_list = [1, 2, 3, 43]
    return render(request, 'lgeng.html', {'u': user_list})

 

lgeng.htmlajax

{% extends 'master.html' %}  {# 導入模板文件 #}

{% block title %}用戶管理{% endblock %}  {# 標題 #}

{% block center %}  {# 內容 #}
    <h1>用戶管理</h1>
    <ul>
        {% for i in u %}
            <li>{{ i }}</li>
        {% endfor %}
    </ul>
{% endblock %}

{% block css %}     {# 自定義css #}
    <style>
        body{
            background-color: white;
        }
    </style>
{% endblock %}

{% block js %}      {# 自定義js #}
    <script></script>
{% endblock %}

 

master.htmlshell

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="/static/commons.css">
    <style>
        .pg-header{
            height: 48px;
            background-color: seashell;
            color: green;
        }
    </style>
    {% block css %}{% endblock %}  {# 自定義css使用 #}
</head>
<body>
    <div class="pg-header">主機管理</div>
    {% block center %}{% endblock %}
    <script src="/static/jquery.js"></script>
    {% block js %}{% endblock %}   {# 自定義js使用 #}
</body>
</html>

 

二、include

一個html只能繼承一個母版,而對於一些小組件、常用的,能夠經過導入實現。一個html中能夠有多個include數據庫

lgeng.html 內增長django

{% block center %}  # 內容
    <h1>用戶管理</h1>

    {% for i in u %}        {# 能夠循環導入 #}
        {% include 'tag.html' %}    {# include 導入 #}
    {% endfor %}

{% endblock %}

 

tag.html瀏覽器

{{ u }}     {# 導入文件中也可使用模板語言 #}
<form>
    <input type="text" />
    <input type="submit" />
</form>  

 

django 是把全部母版、include 合併成一個總的字符串後,在進行渲染。markdown

三、自定義simple_tag

好比在模板語言裏,傳入值5,讓返回25,或傳入一個列表只顯示前三個,等對值的二次處理。

在模板語言中,提供了部份內置功能。有些功能不夠用時就須要自定義python函數實現。

  • 內置功能 —> simple_tag
{{ time_obj|date:"Y-m-d H:i:s"}}  # 對傳入轉爲日期時間格式
{{ str_obj|truncatewords:"30" }}  # 截取前三十個字符
{{ my_list|first|upper }}  # 把第一個字符大寫
{{ name|lower }}  # 把傳入值小寫

 

  • 自定義simple_tag

分兩種方式,總結以下

# 兩種方式相同配置
    a. app下建立templatetags目錄  (templatetags模塊 --- python package )
    b. 目錄下任意xxoo.py文件,建立template對象 register
        from django import template
        register = template.Library()

# 第一種方式:simple_tag
    c. 定義:裝飾函數
        @register.simple_tag
        def func(a1,a2,a3....)
            return "asdfasd"
    d. 配置:settings中註冊APP
    e. 引用:哪裏用哪裏頂部 {% load xxoo %}
    f. 使用:{% 函數名 arg1 arg2 %}
    # 缺點: 不能做爲if條件
    # 優勢: 參數任意

# 第二種方式:filter
    c.定義:裝飾函數
        @register.filter
        def func(a1,a2)
            return "asdfasd"
    d. 配置:settings中註冊APP
    e. 引用:部 {% load xxoo %}  # 引用母版extend時,load在extend下面。
    f. 使用:{ 參數1|函數名:"參數二" }}  # 傳多個,把參數二自定義「a,b,c」多個,本身處理
    # 缺點: 最多兩個參數,不能加空格
    # 優勢: 能做爲if條件

 

使用:

app01/templatetags/xxoo.py

from django import template

register = template.Library()

@register.simple_tag  # 第一種方式
def houyafan(a1,a2):
    return a1 + a2

@register.filter  # 第二種方式
def jingze(a1,a2):
    return a1 + a2

 

settings.py

INSTALLED_APPS = [
    '……………………',
    'app01',
]

 

templates/tpl4.html

{% load xxoo %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{% houyafan 2 7 %}</h1>

    <h1>{{ "maliya"|jingze:"Laoshi" }}</h1>
</body>
</html>

 

urls.py url(r'^tpl', views.tpl),

views.py

def tpl(request):
    return render(request,"tpl4.html")

 

3、Cookie

把瀏覽器的cookie禁用掉,全部涉及到登陸的網站都不能登陸使用了。

Cookie :客戶端瀏覽器上的一個文件,相似於鍵值對字典存儲。換瀏覽器就不行了。

基於這個功能能夠實現用戶的登陸認證,但cookie不是專門用來作用戶驗證登陸的,只不過是利用這個特性實現用戶登陸。

urls.py

url(r'^login/', views.login),
url(r'^index/', views.index),

 

views.py

from django.shortcuts import render, HttpResponse,redirect
user_info = {
    "lgeng00":{"pwd":"123456"},
    "lgeng01":{"pwd":"123456"},
}
def login(request):
    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)
        if not dic:
            return render(request,"login.html")
        if dic['pwd'] == p:
            res = redirect('/index/')
            res.set_cookie("username111", u)    ## 設置cookie
            return res
        else:
            return render(request,'login.html')

def index(request):
    # 獲取當前已登陸的用戶
    v = request.COOKIES.get("username111")
    if not v:
        return redirect('/login/')
    return render(request,'index.html',{'current_user': v})

 

login.html

<body>
    <form action="/login/" method="POST">
        <input type="text" name="username" placeholder="用戶名" />
        <input type="password" name="pwd" placeholder="密碼" />
        <input type="submit" />
    </form>
</body>

 

index.html

<body>
    <h1>歡迎登陸:{{ current_user }}</h1>
</body>

 

一、獲取Cookie:

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    參數:
        default: 默認值
           salt: 加密鹽
        max_age: 後臺控制過時時間

 

二、設置Cookie:

rep = HttpResponse(...) 或 rep = render(request, ...)

rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密鹽',...)
    參數:
        key,             鍵
        value='',        值
        max_age=None,    超時時間
        expires=None,    超時時間(IE requires expires, so set it if hasn't been already.)
        path='/',        Cookie生效的路徑,/ 表示根路徑,特殊的
        跟路徑的cookie能夠被網站的任何url的頁面訪問,如"/index",只能index下能訪問
        domain=None,     Cookie生效的域名,在哪一個子url下生效
        secure=False,    https傳輸(https時,設爲ture)
        httponly=True    只能http協議傳輸,沒法被JavaScript獲取(不是絕對,底層抓包能夠獲取到也能夠被覆蓋)
def cookie(request):
# 獲取 Cookie
    # request.COOKIES                   # 客戶端發來的全部Cookie
    # request.COOKIES['username111']    # 這個Cookie,就是字典
    request.COOKIES.get('username111')

# 設置 Cookie
    res = render(request,'index.html')
    res = redirect('/index/')

    res.set_cookie('key',"value")  # 設置cookie,關閉瀏覽器失效
    res.set_cookie('key',"value",max_age=10)  # 設置cookie, N秒後失效

    # expires:設置cookie, 截止時間後失效
    import datetime
    current_date = datetime.datetime.utcnow()
    current_date = current_date + datetime.timedelta(seconds=5)
    res.set_cookie('key',"value",expires=current_date)
# cookie 加密鹽
    obj = HttpResponse('s')
    obj.set_signed_cookie('username',"kangbazi",salt="asdfasdf") # 加密鹽
    request.get_signed_cookie('username',salt="asdfasdf")  # 加密鹽獲取

 

4、視圖

一、獲取用戶請求相關信息以及請求頭

客戶端發來的數據不僅是get、post、文件等信息,還有基本的請求頭,cookie、session等

想查看客戶端發來的數據request提供了哪些方法?

  • 先找到對象的類:print(tyep(request))

  • 導入類,查看類的內容 from django.core.handlers.wsgi import WSGIRequest

    request.environ 封裝了全部用戶請求信息,原生數據

    from django.core.handlers.wsgi import WSGIRequest
    
    for k,v in request.environ.items():
      print(k,v)
    print(request.environ['HTTP_USER_AGENT'])  # 客戶端終端信息

     

二、CBV和FBV用戶認證裝飾器

urls.py

    url(r'^login/', views.login),
    url(r'^index/', views.index),
    url(r'^order/', views.Order.as_view()),

 

views.py

######################  裝飾器函數  ###########################
def auth(func):
    def inner(reqeust,*args,**kwargs):
        v = reqeust.COOKIES.get('username111')
        if not v:
            return redirect('/login/')
        return func(reqeust, *args,**kwargs)
    return inner
######################  FBV 認證裝飾  #########################
@auth
def index(reqeust):
    # 獲取當前已經登陸的用戶
    v = reqeust.COOKIES.get('username111')
    return render(reqeust,'index.html',{'current_user': v})
######################  FBV 認證裝飾  #########################
from django import views
from django.utils.decorators import method_decorator  # 須要導入模塊

    #****** 第三種:給類加、指定dispatch,同第二種,不須要多寫個函數 ******
@method_decorator(auth,name='dispatch')
class Order(views.View):

    # @method_decorator(auth)  #===== 第二種:dispatch加,方法均有 =====
    # def dispatch(self, request, *args, **kwargs):
    #     return super(Order,self).dispatch(request, *args, **kwargs)

    # @method_decorator(auth)  #--------- 第一種:每一個函數都加 ---------
    def get(self,reqeust):
        v = reqeust.COOKIES.get('username111')
        return render(reqeust,'index.html',{'current_user': v})
    # @method_decorator(auth)  #--------- 第一種:每一個函數都加 ---------
    def post(self,reqeust):
        v = reqeust.COOKIES.get('username111')
        return render(reqeust,'index.html',{'current_user': v})

 

1、以前內容回顧

1、請求週期
        url> 路由 > 函數或類 > 返回字符串或者模板語言?

        Form表單提交:
            提交 -> url > 函數或類中的方法 
                                - ....
                                HttpResponse('....')
                                render(request,'index.html')
                                redirect('/index/')
             用戶  <————  返回字符串
             (當接受到redirect時)自動發起另一個請求
             --> url   .....

        Ajax:
            $.ajax({
                url: '/index/',
                data: {'k': 'v', 'list': [1,2,3,4], 'k3': JSON.stringfy({'k1': 'v'})},    // $(form對象).serilize()  
          //data:$('form').serilize() //-->:user=abc&pwd=aa&add=abc&email=aba&birth=aba&group_id=3 type:
'POST', dataType: 'JSON': traditional: true, # 使單值、列表等均可以發向後臺 success:function(d){ location.reload() # 本身刷新 location.href = "某個地址" # 本身跳轉 } }) 提交 -> url -> 函數或類中的方法 HttpResponse('{}') render(request, 'index.html', {'name': 'v1'}) <h1>{{ name }}</h1> --> <h1>v1</h1> redirect...Ajax裏不能夠 用戶 <<<<< 字符串 2、路由系統URL a. /index/ -> 函數或類 b. /index/(\d+) -> 函數或類 c. /index/(?P<nid>\d+) -> 函數或類 d. /index/(?P<nid>\d+) name='root' -> 函數或類 reverse() {% url 'root' 1%} e. /crm/ include('app01.urls') -> 路由分發 f. 默認值 # url第三個參數做爲默認參數傳遞到view函數裏 url(r'^index/', views.index, {'name': 'root'}), def index(request,name): print(name) return HttpResponse('OK') g. 命名空間 /admin/ include('app01.urls',namespace='m1') /crm/ include('app01.urls',namespace='m2')
app01.urls

app_name = 'app01' <-- 添加 app_name
urlpatterns=[   url(r'/
index/', views.index, name = 'n1'),
         url(r'/home/' , views.home, name = 'n2)'
        ]
reverser('m1:n1') --> /admin/index/
reverser('m1:n2') --> /admin/home/
reverser('m2:n1') --> /crm/index/
reverser('m2:n2') --> /crm/home/
       
3、獲取請求 def func(request): request.POST request.GET request.FILES request.getlist request.method request.path_info return render,HttpResponse,redirect 4、模板 render(request, 'index.html') # for # if # 索引 用 . keys values items all (都不加括號) 5、數據庫操做 class User(models.Model): username = models.CharField(max_length=32) email = models.EmailField() 有驗證功能 Django Admin 無驗證功能: User.objects.create(username='root',email='asdfasdfasdfasdf') User.objects.filter(id=1).update(email='666') class UserType(models.Model): name = models.CharField(max_length=32) # 外鍵 class User(models.Model): username = models.CharField(max_length=32) email = models.EmailField() user_type = models.ForeignKey("UserType") # 數據庫操做 user_list = User.objects.all() # 獲取對象列表 for obj user_list: obj.username,obj.email,obj.user_type_id,obj.user_type.name,obj.user_type.id user = User.objects.get(id=1) # 獲取單個對象 user. # 對象跨表用點,條件裏用雙下劃線 User.objects.all().values("username","user_type__name",) # 多對多 class UserType(models.Model): name = models.CharField(max_length=32) class User(models.Model): username = models.CharField(max_length=32) email = models.EmailField() user_type = models.ForeignKey("UserType") m = models.ManyToMany('UserGroup') class UserGroup(models.Model): name = .... obj = User.objects.get(id=1) obj.m.add(2) obj.m.add(2,3) obj.m.add(*[1,2,3]) obj.m.remove(...) obj.m.clear() obj.m.set([1,2,3,4,5]) # 這裏列表前不加* # 多個組,UserGroup對象 obj.m.all() obj.m.filter(name='CTO')

 

補充:默認值

看上面內容

補充:命名空間

a. project.urls.py

兩個url同指向一個

from django.conf.urls import url,include

urlpatterns = [                     # namespace  命名空間
    url(r'^a/', include('app01.urls', namespace='m1')),
    url(r'^b/', include('app01.urls', namespace='m2')),
]

 

b. app01.urls.py

from django.conf.urls import url
from app01 import views

app_name = 'app01'
urlpatterns = [
    url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]

 

c. app01.views.py

def detail(request):
    return HttpResponse('pk')

 

以上定義帶命名空間的url以後,使用name反向生成URL(反解)的時候,應該以下:

  • v = reverse('m1:detail') python代碼裏
  • {% url 'm1:detail' %} 模板語言裏

django中的路由系統和其餘語言的框架有所不一樣,在django中每個請求的url都要有一條路由映射,這樣才能將請求交給對一個的view中的函數去處理。其餘大部分的Web框架則是對一類的url請求作一條路由映射,從而使路由系統變得簡潔。


轉載請務必保留此出處:http://www.cnblogs.com/lgeng/articles/7365723.html

 

 <!--   END   -->

 

 

 

 

 

 

 

《版權說明》: 本文轉自 -- http://blog.csdn.net/fgf00/article/details/54018066

相關文章
相關標籤/搜索