Django ~ 2

一 模版

一模版的組成javascript

   HTML代碼+邏輯控制代碼css

二 邏輯控制代碼的組成html

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

   {{var_name}}python

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

   {%load staticfiles%}web

   3 過濾器(filter)的使用數據庫

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

三 經常使用標籤bootstrap

   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

一、cookie不屬於http協議範圍,因爲http協議沒法保持狀態,但實際狀況,咱們卻又須要「保持狀態」,所以cookie就是在這樣一個場景下誕生。

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

二、cookie雖然在必定程度上解決了「保持狀態」的需求,可是因爲cookie自己最大支持4096字節,以及cookie自己保存在客戶端,可能被攔截或竊取,所以就須要有一種新的東西,它能支持更多的字節,而且他保存在服務器,有較高的安全性。這就是session。

問題來了,基於http協議的無狀態特徵,服務器根本就不知道訪問者是「誰」。那麼上述的cookie就起到橋接的做用。

咱們能夠給每一個客戶端的cookie分配一個惟一的id,這樣用戶在訪問時,經過cookie,服務器就知道來的人是「誰」。而後咱們再根據不一樣的cookie的id,在服務器上保存一段時間的私密資料,如「帳號密碼」等等。

三、總結而言:cookie彌補了http無狀態的不足,讓服務器知道來的人是「誰」;可是cookie以文本的形式保存在本地,自身安全性較差;因此咱們就經過cookie識別不一樣的用戶,對應的在session裏保存私密的信息以及超過4096字節的文本。

四、另外,上述所說的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

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

一、login頁面正確登陸的話,後臺頁面能夠獲取到瀏覽器攜帶的cookie的。

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

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

四、服務端能夠經過預設的key值取出session的內容並打印到前段

從火狐瀏覽器裏查看cookie

wKioL1bm5aLicB3pAAC_XkZOUds501.png

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

wKioL1bm5imRTMYYAABvKzZiJig955.png

wKiom1bm6EHiV1i0AADUm8yxkhs649.png

下面咱們再來最後的總結一下cookie和session的知識

1、操做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: '/' });

2、操做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

相關文章
相關標籤/搜索