django基礎二


一 模版

一模版的組成

   HTML代碼+邏輯控制代碼

二 邏輯控制代碼的組成

   1  變量(使用雙大括號來引用變量)

   {{var_name}}

   2  標簽(tag)的使用(使用大括號和百分比的組合來表示使用tag)

   {%load staticfiles%}

   3 過濾器(filter)的使用

     {{ship_date|date:"Fj,Y"}},ship_date變量傳給data過濾器,date過濾器通過使用"FJ,Y"這幾個參數來格式化日期數據。"|"代表類似Unix命令中的管道操作。

三 常用標簽

   1  {%if%} 的使用

      可以使用你的and,or,not來組織的邏輯。但不允許and和or同時出現在條件語句中。新版本中已經支持了                 {%elif%} 這樣的用法。

    2  {% for %}的使用

       用來循環一個序列, 還可以使用reserser關鍵字來進行倒序遍歷,一般可以先用if語句判斷序列是否為空,再進行遍歷;還可以使用empty關鍵字來進行為空時的跳轉

        

 3  {%csrf_token%}

     用於生成csrf_token的標簽,用於防治跨站攻擊驗證。

     注意如果你在view的index里用的是render_to_response方法,此時標簽由於沒有上下文的關系所以沒有效果,需要:

     

   或者直接使用render。

   其實,這里是會生成一個input標簽,和其他表單標簽一起提交給后台的。

4   {% load %}: 加載標簽庫

5   {% url %}:  引用路由配置的地址

     

6   {% with %}:用更簡單的變量名替代復雜的變量名

     

7   {% verbatim %}: 禁止render  

{% verbatim %}
{{ hello }}
{% endverbatim %}

 

四 常用過濾器

   1  add          :   給變量加上相應的值

   2  addslashes:    給變量中的引號前加上斜線

   3  capfirst     :    首字母大寫

   4  cut           :   從字符串中移除指定的字符

   5  date         :   格式化日期字符串

   6  default     :   如果值是False,就替換成設置的默認值,否則就是用本來的值

   7  default_if_none:如果值是None,就替換成設置的默認值,否則就使用本來的值

  

五 模版的包含和繼承

   包含:{% include %} 允許在模版中包含其他模版的內容。

標簽的參數可以是:模版名稱,變量,字符串

      {% include 'nav.html' %}

      {% include 'app/nav.html'%}

      {% include template_name %}

   繼承:本質上說,模版繼承就是先構造一個基礎框架模版,而后在其子模版中對它所包含站點共用部分和定義進行重載。

        1    {% block %}

             定義塊

        2    {% extends %}

             繼承父模版

  

  注意:

        1 包含和繼承可以把一些共用的網頁模塊獨立出來,以減少代碼的冗余。

        2  如果在模塊里使用{% extends %}d的話,這個標簽必須在所有模版標簽的最前面,否則模版繼承不工作。

        3  通常盡可能模版里的{% block %}越多越好,子模版不必定義所有的父block

        4  如果你需要父模版的塊內容,{{block.super}}變量可以幫你完成工作,當你需要為父塊添加內容而不是取代它的時候這就很有用。

        5  不能在同一模版(無論是父模版還是子模版)里定義多個同名{% block %} ,因為塊標簽同時在兩個地方工作,不僅在子模版中,而且在父模版中也填充內容,如果子模版有兩個同名的標簽,父模版將不能決定使用哪一個塊內容來使用。

 二 admin的配置

django admin是django自帶的一個后台app,提供了后台的管理功能。

基礎知識點:

一  認識ModelAdmin

   管理界面的定制類,如需擴展特定的model界面需從該類繼承

二 注冊medel類到admin的兩種方式:

     1   使用register的方法

     2   使用register的裝飾器

三 掌握一些常用的設置技巧

    list_display:  指定要顯示的字段

    search_fields:指定搜索的字段

    list_filter: 指定列表過濾器

    ordering:指定排序字段

    

三 Form

一 什么是Form?什么是DjangoForm?

Django表單系統中,所有的表單類都作為django.forms.Form的子類創建,包括ModelForm

 

關於django的表單系統,主要分兩種

基於django.forms.Form:所有表單類的父類

基於django.forms.ModelForm:可以和模型類綁定的Form

實例:實現添加出版社信息的功能

二 不使用Django Form的情況

    

 

三  使用Form的情況

    首先,在app01中建立forms.py

######################################################### 


#app01下新建的forms.py
from django import forms

class Mypub_form(forms.Form):
    name = forms.CharField(label='名稱',error_messages={'required':'必填'})
    address = forms.CharField(label='地址',error_messages={'required':'必填'})
    city = forms.CharField(label='城市',error_messages={'required':'必填'})
    state_province = forms.CharField(label='省份',error_messages={'required':'必填'})
    country = forms.CharField(label='國家',error_messages={'required':'必填'})
    website = forms.URLField(label='網址',error_messages={'required':'必填'})
#######################################################
#app01.views
def add_publisher(req):
    if req.method=='POST':
        # #不使用django form
        # print(req.POST)
        # name=req.POST['name']
        # address=req.POST.get('address')
        # city=req.POST['city']
        # province=req.POST['province']
        # country=req.POST['country']
        # website=req.POST['website']
        # Publisher.objects.create(
        #     name=name,
        #     city=city,
        #     address=address,
        #     state_province=province,
        #     country=country,
        #     website=website
        # )
        # return HttpResponse("添加出版社信息成功!")

        #使用django form的情況

        Mypub_form_obj=Mypub_form(req.POST)
        if Mypub_form_obj.is_valid():
            Publisher.objects.create(
                name=Mypub_form_obj.cleaned_data["name"],
                address=Mypub_form_obj.cleaned_data["address"],
                city=Mypub_form_obj.cleaned_data["city"],
                state_province=Mypub_form_obj.cleaned_data["state_province"],
                country=Mypub_form_obj.cleaned_data["country"],
                website=Mypub_form_obj.cleaned_data["website"],
            )

            return HttpResponse("添加出版社信息成功!")
    else:
        Mypub_form_obj=Mypub_form()
    return render(req,'add_publisher.html',locals())
#######################################################
#add_publisher.html
<body>
     <form action="{% url 'add_pub' %}" method="post">
         {% csrf_token %}
{#           名稱:<input type="text" name="name"><br>#}
{#           地址:<input type="text" name="address"><br>#}
{#           城市:<input type="text" name="city"><br>#}
{#           省份:<input type="text" name="province"><br>#}
{#           國家:<input type="text" name="country"><br>#}
{#           網址:<input type="text" name="website"><br>#}
{#           <input type="submit" value="提交"><br>#}


         {{ Mypub_form_obj.as_p }}
         <input type="submit" value="提交"><br>
     </form>
</body>
View Code

四 使用ModelForm的情況

#######################################################
#app01.views
def add_publisher(req):
    if req.method=='POST':
        # #不使用django form
        # print(req.POST)
        # name=req.POST['name']
        # address=req.POST.get('address')
        # city=req.POST['city']
        # province=req.POST['province']
        # country=req.POST['country']
        # website=req.POST['website']
        # Publisher.objects.create(
        #     name=name,
        #     city=city,
        #     address=address,
        #     state_province=province,
        #     country=country,
        #     website=website
        # )
        # return HttpResponse("添加出版社信息成功!")

        #使用django form的情況

        Mypub_form_obj=Mypub_form(req.POST)
        if Mypub_form_obj.is_valid():
            # Publisher.objects.create(
            #     name=Mypub_form_obj.cleaned_data["name"],
            #     address=Mypub_form_obj.cleaned_data["address"],
            #     city=Mypub_form_obj.cleaned_data["city"],
            #     state_province=Mypub_form_obj.cleaned_data["state_province"],
            #     country=Mypub_form_obj.cleaned_data["country"],
            #     website=Mypub_form_obj.cleaned_data["website"],
            # )
            Mypub_form_obj.save()

            return HttpResponse("添加出版社信息成功!")
    else:
        Mypub_form_obj=Mypub_form()
    return render(req,'add_publisher.html',locals())
#######################################################
#add_publisher.html
<body>
     <form action="{% url 'add_pub' %}" method="post">
         {% csrf_token %}
{#           名稱:<input type="text" name="name"><br>#}
{#           地址:<input type="text" name="address"><br>#}
{#           城市:<input type="text" name="city"><br>#}
{#           省份:<input type="text" name="province"><br>#}
{#           國家:<input type="text" name="country"><br>#}
{#           網址:<input type="text" name="website"><br>#}
{#           <input type="submit" value="提交"><br>#}


         {{ Mypub_form_obj.as_p }}
         <input type="submit" value="提交"><br>
     </form>
</body>
View Code

思考:為什么有的顯示漢子,有的顯示英文

總結:

    使用Django中Form可以大大簡化代碼,常用的表單功能特性都整合到了Form中,而ModelForm可以和Model進行綁定,更進一步簡化操作。   

 

四 Form 驗證

    django提供了3種方式來驗證表單

實例:自定義驗證,不能插入重名的出版社名稱。

一 表單字段的驗證器

   

二 clean_filedname,驗證字段,針對某個字段進行驗證。

   

三 表單clean方法,可針對整個表單進行驗證

   

    像注冊時需要輸入兩次密碼的驗證,用clean來做就非常好,因為前兩種都只是針對某一個字段進行驗證,而確認密碼則需要將兩個字段信息都拿來進行匹配。

 五 cookie和session

1、cookie不屬於http協議范圍,由於http協議無法保持狀態,但實際情況,我們卻又需要“保持狀態”,因此cookie就是在這樣一個場景下誕生。

cookie的工作原理是:由服務器產生內容,瀏覽器收到請求后保存在本地;當瀏覽器再次訪問時,瀏覽器會自動帶上cookie,這樣服務器就能通過cookie的內容來判斷這個是“誰”了。

2、cookie雖然在一定程度上解決了“保持狀態”的需求,但是由於cookie本身最大支持4096字節,以及cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的字節,並且他保存在服務器,有較高的安全性。這就是session。

問題來了,基於http協議的無狀態特征,服務器根本就不知道訪問者是“誰”。那么上述的cookie就起到橋接的作用。

我們可以給每個客戶端的cookie分配一個唯一的id,這樣用戶在訪問時,通過cookie,服務器就知道來的人是“誰”。然后我們再根據不同的cookie的id,在服務器上保存一段時間的私密資料,如“賬號密碼”等等。

3、總結而言:cookie彌補了http無狀態的不足,讓服務器知道來的人是“誰”;但是cookie以文本的形式保存在本地,自身安全性較差;所以我們就通過cookie識別不同的用戶,對應的在session里保存私密的信息以及超過4096字節的文本。

4、另外,上述所說的cookie和session其實是共通性的東西,不限於語言和框架

 

前幾節的介紹中我們已經有能力制作一個登陸頁面,在驗證了用戶名和密碼的正確性后跳轉到后台的頁面。但是測試后也發現,如果繞過登陸頁面。直接輸入后台的url地址也可以直接訪問的。這個顯然是不合理的。其實我們缺失的就是cookie和session配合的驗證。有了這個驗證過程,我們就可以實現和其他網站一樣必須登錄才能進入后台頁面了。

      先說一下這種認證的機制。每當我們使用一款瀏覽器訪問一個登陸頁面的時候,一旦我們通過了認證。服務器端就會發送一組隨機唯一的字符串(假設是123abc)到瀏覽器端,這個被存儲在瀏覽端的東西就叫cookie。而服務器端也會自己存儲一下用戶當前的狀態,比如login=true,username=hahaha之類的用戶信息。但是這種存儲是以字典形式存儲的,字典的唯一key就是剛才發給用戶的唯一的cookie值。那么如果在服務器端查看session信息的話,理論上就會看到如下樣子的字典

{'123abc':{'login':true,'username:hahaha'}}

因為每個cookie都是唯一的,所以我們在電腦上換個瀏覽器再登陸同一個網站也需要再次驗證。那么為什么說我們只是理論上看到這樣子的字典呢?因為處於安全性的考慮,其實對於上面那個大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服務器端也是一樣被加密的。所以我們服務器上就算打開session信息看到的也是類似與以下樣子的東西

{'123abc':dasdasdasd1231231da1231231}

借用一張別的大神畫的圖,可以更直觀的看出來cookie和session的關系

wKioL1bmwJqQWT79AACFVu-rqIs465.gif

   

    知道了原理,我們下面就來用代碼實現

先在templates目錄下創建兩個html,login.html負責登錄頁面。backend頁面代表后台頁面

wKioL1bm3rygxB5QAAAoQMv4T8o844.png

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" href="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <form action="login.html" method="post">
            <div class="form-group">
                <label class="sr-only">username</label>
                <input type="text" class="form-control" name="username" placeholder="用戶名"/>
            </div>
            <div class="form-group">
                <label class="sr-only">Password</label>
                <input type="password" class="form-control" name="passwd" placeholder="密碼"/>
            </div>
            <div class="form-group">
                <input class="btn btn-primary" type="submit" value="http://830909.blog.51cto.com/8311014/Submit">
            </div>
        </form>
</div>
<script type="application/Javascript" src="http://830909.blog.51cto.com/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
</body>
</html>

backend.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>backend</title>
    <link rel="stylesheet" href="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="http://830909.blog.51cto.com/static/css/commons.css">
</head>
<body>
<div class="container">
    <h2>cookie 內容是 {{ cookie_content }}</h2>
    <h2>session 內容是 {{ session_content }}</h2>
    <h2>登錄用戶名 :{{ username }}</h2>
    <a href="http://830909.blog.51cto.com/logout/">注銷</a>
</div>
<script type="application/javascript" src="http://830909.blog.51cto.com/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="http://830909.blog.51cto.com/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
</body>
</html>

第二步 編輯app01應用下的views.py文件,編寫代碼邏輯部分

wKioL1bm4QnCtWaCAAAwVBjCprc461.png

views.py

 

# /usr/bin/env python
# coding:utf-8
from django.shortcuts import render
from django.shortcuts import redirect
def login(request):
    if request.method=="POST":
        username=request.POST['username']
        pwd=request.POST['passwd']
        if username=='abc' and pwd=='123':
            #設置session內部的字典內容
            request.session['is_login']='true'
            request.session['username']='abc'
            #登錄成功就將url重定向到后台的url
            return redirect('/backend/')
    #登錄不成功或第一訪問就停留在登錄頁面
    return render(request,'login.html')
def backend(request):
    """
    這里必須用讀取字典的get()方法把is_login的value缺省設置為False,
    當用戶訪問backend這個url先嘗試獲取這個瀏覽器對應的session中的
    is_login的值。如果對方登錄成功的話,在login里就已經把is_login
    的值修改為了True,反之這個值就是False的
    """
    is_login=request.session.get('is_login',False)
    #如果為真,就說明用戶是正常登陸的
    if is_login:
        #獲取字典的內容並傳入頁面文件
        cookie_content=request.COOKIES
        session_content=request.session
        username=request.session['username']
        return render(request,'backend.html',
                      {
            'cookie_content':cookie_content,
            'session_content':session_content,
            'username':username
                      })
    else:
        """
        如果訪問的時候沒有攜帶正確的session,
        就直接被重定向url回login頁面
        """
        return redirect('/login/')
def logout(request):
    """
    直接通過request.session['is_login']回去返回的時候,
    如果is_login對應的value值不存在會導致程序異常。所以
    需要做異常處理
    """
    try:
        #刪除is_login對應的value值
        del request.session['is_login']
    except KeyError:
        pass
    #點擊注銷之后,直接重定向回登錄頁面
    return redirect('/login/')

第三步,編輯mydjango目錄下的urls.py文件。設置函數與頁面的綁定關系

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^backend/', views.backend),
    url(r'^logout/', views.logout),
]

wKiom1bm4D7AGoi8AADg0sOk10k285.png

最后打開瀏覽器直接訪問/backend/頁面的時候直接就被重定向到了/login/

wKioL1bm4Ynh_bOzAABPcTDBX40769.png

只有在輸入了正確的用戶名和密碼之后才進入到了/backend/頁面

wKiom1bm4UOjEwzlAAE9se9_78U441.png

從上圖中我們看到有一下幾點:

1、login頁面正確登錄的話,后台頁面可以獲取到瀏覽器攜帶的cookie的。

2、第一行的sessionid其實就是cookie值

3、session的內容是加密的,從客戶端獲取不到session的內容

4、服務端可以通過預設的key值取出session的內容並打印到前段

從火狐瀏覽器里查看cookie

wKioL1bm5aLicB3pAAC_XkZOUds501.png

django的session默認是存儲在數據庫里的,我們再到數據庫查看一下真正session內容

wKioL1bm5imRTMYYAABvKzZiJig955.png

wKiom1bm6EHiV1i0AADUm8yxkhs649.png

下面我們再來最后的總結一下cookie和session的知識

一、操作Cookie

  獲取cookie:request.COOKIES[key]

  設置cookie:response.set_cookie(key,value)

由於cookie保存在客戶端的電腦上,所以,jquery也可以操作cookie。

<script src='http://830909.blog.51cto.com/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });

二、操作Session(session默認在服務器端保存15天)

  獲取session:request.session[key]

  設置session:reqeust.session[key] = value

  刪除session:del request.session[key]    

(這個刪除其實就是把數據庫的session_data更新為一個其他的值了,並沒有立即刪除)

 

request.session.set_expiry(value)
* 如果value是個整數,session會在些秒數后失效。
* 如果value是個datatime或timedelta,session就會在這個時間后失效。
* 如果value是0,用戶關閉瀏覽器session就會失效。
* 如果value是None,session會依賴全局session失效策略。

 

 

參考:
       http://www.07net01.com/2016/03/1364624.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM