03 Django視圖

  • 功能
    • 接受Web請求HttpRequest,進行邏輯處理,與 M 和 T 進行交互,返回 Web 響應 HttpResponse 給請求者
  • 示例項目的建立
    • 建立項目 test3

django-admin startproject test3javascript

   

  • 進入項目目錄後,建立應用 booktest

cd test3 html

python manage.py startapp booktestjava

   

  • 在 test3/settings.py 中 INSTALLED_APPS 項安裝應用
  • 在 test3/settings.py 中 DATABASES 項配置使用 MYSQL 數據庫,參照配置使用 mysql 數據庫
  • 在 test3/settings.py 中 TEMPLATES 項配置模板查找路徑,參照模板文件的使用
  • 使用示圖的過程
    • 視圖就是一個python函數,被定義在"應用/views.py"文件中。 使用視圖時須要進行兩方面操做,兩個操做不分前後
    • 在 '應用/views.py' 中定義視圖
      • 在 booktest/views.py 中定義視圖函數index

def index(request): python

    return HttpResponse("視圖函數index")mysql

  • 配置URLconf,將視圖函數和url對應起來
    • 在test3/urls.py中編輯加入以下代碼:

from django.conf.urls import include, url jquery

from django.contrib import admin ajax

   

urlpatterns = [ 正則表達式

    url(r'^admin/', include(admin.site.urls)),sql

    url(r'^', include('booktest.urls')), #這句代碼是新加入的,包含booktest應用中的urls文件 數據庫

]

  

  • 在booktest目錄下建立urls.py文件並編輯其內容以下:

from django.conf.urls import url #導入url函數

   

from booktest import views #導入視圖模塊

   

urlpatterns = [

    url(r'^$', views.index), #創建urlviews.index視圖函數的關聯

]

  

  • 啓動服務器,並經過瀏覽器訪問  http://127.0.0.1:8000  頁面顯示以下:
  • url 匹配過程
    • 示意圖
    • 過程,以訪問 http://127.0.0.1:8000/aindex?a=1 爲例,請求的url被看作是一個普通的python字符串,進行匹配時不包括域名、get或post參數
      • 去除域名和後面的參數,剩下 /aindex,再把前面的的 / 去掉,剩下 aindex
      • 拿 aindex 先到項目的 url.py 文件中進行從上到下的匹配,匹配成功以後執行後面對應的處理動做。對於圖中的示例來講,就是把匹配成功的部分 a 字符去除,而後拿剩下的部分 index 到應用的 urls.py 文件中再進行從上到下的匹配
      • 若是匹配成功,則調用相應的視圖產生的內容返回給客戶端。若是匹配失敗則產生 404 錯誤
  • 錯誤視圖
    • 404
      • 找不到頁面,關閉調試模式以後,默認會顯示一個標準的錯誤頁面,若是要顯示自定義的頁面,則須要在 templates 目錄下面自定義一個 404.html 文件
      • 出現 404 的可能緣由
        • url 沒有配置
        • url 配置錯誤
    • 500
      • 服務器錯誤,默認會顯示一個標準的錯誤頁面,若是要顯示自定義的頁面,則須要在 templates 目錄下面自定義一個 500.html 文件
      • 出現 500 的可能緣由
        • 視圖出錯
  • 捕獲 url 參數
    • 位置參數
      • 直接使用小括號,經過位置參數傳遞給視圖。
      • 使用以下的正則表達式

url(r'^delete(\d+)/$',views.show_arg),

  • 修改視圖 show_arg 以下:
    • 其中參數的名字能夠爲任意值,但儘可能要作到見名知意

def show_arg(request,id):

    return HttpResponse('show arg %s'%id)

  • 在瀏覽器中輸入相應的地址,以下:
  • 關鍵字參數
    • 在正則表達式部分爲組命名
    • 正則表達式以下:

# 其中?P部分表示爲這個參數定義的名稱爲id,能夠是其它名稱,起名作到見名知意。

url(r'^delete(?P<id1>\d+)/$',views.show_arg), 

  • 修改視圖 show_arg 以下:

# 注意:視圖show_arg此時必需要有一個參數名爲id1,不然報錯。

def show_arg(request,id1):

    return HttpResponse('show %s'%id1) 

  • 在瀏覽器中輸入相應地址,結果以下:
  • HttpRequest 對象
    • 服務器接收到 http 協議的請求後,會根據報文建立 HttpRequest 對象,這個對象不須要咱們建立,直接使用服務器構造好的對象就能夠。視圖的第一個參數必須是 HttpRequest 對象,在django.http 模塊中定義了HttpRequest 對象的 API
    • 屬性(除非特殊說明,屬性都是隻讀的)
      • path:一個字符串,表示請求的頁面的完整路徑,不包含域名和參數部分。
      • method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST'。
        • 在瀏覽器中給出地址發出請求採用get方式,如超連接。
        • 在瀏覽器中點擊表單的提交按鈕發起請求,若是表單的method設置爲post則爲post請求。
      • encoding:一個字符串,表示提交的數據的編碼方式。
        • 若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8。
        • 這個屬性是可寫的,能夠經過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值。
      • GET:QueryDict類型對象,相似於字典,包含get請求方式的全部參數。
      • POST:QueryDict類型對象,相似於字典,包含post請求方式的全部參數。
      • FILES:一個相似於字典的對象,包含全部的上傳文件。
      • COOKIES:一個標準的Python字典,包含全部的cookie,鍵和值都爲字符串。
      • session:一個既可讀又可寫的相似於字典的對象,表示當前的會話,只有當Django 啓用會話的支持時纔可用,詳細內容見"狀態保持"。
  • QueryDict 對象
    • 定義在django.http.QueryDict
    • HttpRequest對象的屬性GET、POST都是QueryDict類型的對象
    • 與 python 字典不一樣,QueryDict類型的對象能夠用來處理同一個鍵帶有多個值的狀況
    • 方法 get():根據鍵獲取值
      • 若是一個鍵同時擁有多個值將獲取最後一個值
      • 若是鍵不存在則返回None值,能夠設置默認值進行後續處理
      • 示例

dict.get('',默認值)

# 可簡寫爲

dict['']

  • 方法 getlist():根據鍵獲取值,值以列表返回,能夠獲取指定鍵的全部值
    • 若是鍵不存在則返回空列表 [],能夠設置默認值進行後續處理

dict.getlist('',默認值)

  • HttpResponse 對象
    • 相關概念
      • 視圖在接收請求並處理後,必須返回HttpResponse對象或子對象
      • 在django.http模塊中定義了HttpResponse對象的API
      • HttpRequest對象由Django建立,HttpResponse對象由開發人員建立
    • 屬性
      • content:表示返回的內容。
      • charset:表示response採用的編碼字符集,默認爲utf-8。
      • status_code:返回的HTTP響應狀態碼。
      • content-type:指定返回數據的的MIME類型,默認爲'text/html'
    • 方法
      • __init__:建立HttpResponse對象後完成返回內容的初始化
      • write:向響應體中寫數據

def get_cookie(request):

    """獲取 cookie """

    response = HttpResponse("<h1>獲取 cookie </h1><br />")

    if 'username' in request.COOKIES:

        response.write("<h2>username: " + request.COOKIES['username'] + "</h2>")

    else:

        response.write("用戶名不存在")

    return response

  • 使用示例

from django.template import RequestContext, loader

...

def index3(request):

    #加載模板

    t1=loader.get_template('booktest/index3.html')

    #構造上下文

    context=RequestContext(request,{'h1':'hello'})

    #使用上下文渲染模板,生成字符串後返回響應對象

    return HttpResponse(t1.render(context))

  • 每次調用模板時都要執行加載、構造上下文、渲染三個步驟,爲了簡化操做,Django定義了render() 函數封裝了以上三個步驟的代碼,定義在django.shortcuts 模塊中

from django.shortcuts import render

...

def index3(request):

    return render(request, 'booktest/index3.html', {'h1': 'hello'})

  • 示例:普通用戶登陸案例

url(r'^login$', views.login),

  • 設計 url 對應的視圖函數 login

def login(request):

    """顯示登陸界面"""

    print(request.method)

    return render(request, 'booktest/login.html')

  • 編寫模板文件 login.html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>登陸頁面</title>

</head>

<body>

    <form method="post", action="/login_check">

        用戶名:<input tyep='text' name='username'><br/>

        密碼:<input type='password', name='password'><br/>

        <input type='submit' value='登陸'>

    </form>

</body>

</html>

url(r'^login_check$', views.login_check),

  • 設計 url 對應的視圖函數 login_check
    • 接收表單提交過來的數據並進行登陸校驗,若用戶名密碼正確則跳轉到登陸成功頁。若失敗在跳轉到登陸頁面。

def login_check(request):

    """登陸校驗視圖"""

    # request.POST 保存的是 post 方式提交的參數,類型爲 QueryDict

    # request.GET 保存的是 get 方式提交的參數, 類型爲 QueryDict

    # 獲取提取的用戶名和密碼

    username = request.POST.get('username', 'default')

    password = request.POST.get('password', 'default')

    print(username + ':' + password)

    # 進行檢驗

    if(username == 'admin' and password == '123'):

        # 用戶名或密碼正確

        return redirect("/index")

    else:

        return redirect("/login")

  • Ajax 請求與 JsonResponse
    • 在瀏覽器中使用javascript發起ajax請求時,須要返回json格式的數據。
    • 類JsonResponse繼承自HttpResponse對象,被定義在django.http模塊中
      • 建立對象時接收字典做爲參數
      • JsonResponse對象的content-type爲'application/json'
    • 示例:ajax 登陸案例
      • 建立目錄 static/js/,並把 jquery 文件拷貝到相應的目錄下
      • 打開test3/settings.py文件,在文件最底部,配置靜態文件查找路徑

STATICFILES_DIRS = [

    os.path.join(BASE_DIR, 'static'),

]

url(r'^login_ajax$', views.login_ajax),

  • 設計 url 對應的視圖函數 login_ajax

def login_ajax(request):

    """ajax 登陸界面"""

    return render(request, 'booktest/login_ajax.html')

  • 編寫模板文件 login_ajax.html

<!DOCTYPE html>

<html lang="zh-cn">

<head>

    <meta charset="UTF-8">

    <title>登陸頁面</title>

    <script src='static/js/jquery-1.12.4.min.js'></script>

    <script>

        $(function(){

            $('#btn').click(function(){

                username = $('#username').val()

                password = $('#password').val()

                $.ajax({

                    'url': '/login_ajax_check',

                    'type': 'post',

                    'data': {'username': username, 'password': password},

                    'dataType': 'json',

                }).success(function(data){

                    // {'res': 1} 表示登陸成功

                    // {'res': 0} 表示登陸失敗

                    if(data.res == 1){

                        location.href = '/index'

                    }

                    else{

                        $('#message').show()

                    }

                })

            })

        })

    </script>

    <style>

        #message{

            display:none;

            color: red;

        }

    </style>

</head>

<body>

    <div>

        用戶名:<input tyep='text' id='username'><br/>

        密碼:<input type='password' id='password'><br/>

        <input type='button' id='btn' value='登陸'>

        <div id="message">用戶名或密碼錯誤</div>

    </div>

</body>

</html>

  

url(r'^login_ajax_check$', views.login_ajax_check), 

  • 設計 url 對應的視圖函數 login_ajax_check

def login_ajax_check(request):

    """ajax 登陸界面用戶名和密碼檢查"""

    username = request.POST.get('username')

    password = request.POST.get('password')

    if(username == 'admin' and password == '123'):

        # 用戶名或密碼正確

        return JsonResponse({'res': 1})

    else:

        return JsonResponse({'res': 0}) 

  • HttpResponseRedriect
    • 當一個邏輯處理完成後,不須要向客戶端呈現數據,而是轉回到其它頁面,如添加成功、修改爲功、刪除成功後顯示數據列表,而數據的列表視圖已經開發完成,此時不須要從新編寫列表的代碼,而是轉到這個視圖就能夠,此時就須要模擬一個用戶請求的效果,從一個視圖轉到另一個視圖,就稱爲重定向
    • Django中提供了 HttpResponseRedirect 對象實現重定向功能,這個類繼承自 HttpResponse,被定義在django.http模塊中,返回的狀態碼爲302
    • 在 django.shortcuts 模塊中爲重定向類提供了簡寫函數 redirect
  • 狀態保持
    • 基本概念
      • 瀏覽器請求服務器是無狀態的。
        • 無狀態指一次用戶請求時,瀏覽器、服務器沒法知道以前這個用戶作過什麼,每次請求都是一次新的請求。
        • 無狀態的應用層面的緣由是:瀏覽器和服務器之間的通訊都遵照HTTP協議
        • 根本緣由是:瀏覽器與服務器是使用Socket套接字進行通訊的,服務器將請求結果返回給瀏覽器以後,會關閉當前的Socket鏈接,並且服務器也會在處理頁面完畢以後銷燬頁面對象。
      • 有時須要保存下來用戶瀏覽的狀態,好比用戶是否登陸過,瀏覽過哪些商品等。 實現狀態保持主要有兩種方式:
        • 在客戶端存儲信息使用Cookie
        • 在服務器端存儲信息使用Session
    • Cookie
      • 基本概念
        • Cookie,有時也用其複數形式 Cookies,指某些網站爲了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端上的數據(一般通過加密)。Cookie 最先是網景公司的前僱員 Lou Montulli 在1993年3月的發明。Cookie 是由服務器端生成,發送給 User-Agent (通常是瀏覽器),瀏覽器會將 Cookie 的 key/value 保存到某個目錄下的文本文件內,下次請求同一網站時就發送該 Cookie 給服務器(前提是瀏覽器設置爲啓用 cookie)。Cookie 名稱和值能夠由服務器端開發本身定義,這樣服務器能夠知道該用戶是不是合法用戶以及是否須要從新登陸等。服務器能夠利用 Cookies 包含信息的任意性來篩選並常常性維護這些信息,以判斷在 HTTP 傳輸中的狀態。
        • Cookie 是存儲在瀏覽器中的一段純文本信息,建議不要存儲敏感信息如密碼,由於電腦上的瀏覽器可能被其它人使用
      • 特色
        • Cookie 以鍵值對的格式進行信息的存儲
        • Cookie 基於域名安全,不一樣域名的 Cookie 是不能互相訪問的,如訪問 itcast.cn 時向瀏覽器中寫了 Cookie 信息,使用同一瀏覽器訪問baidu.com 時,沒法訪問到 itcast.cn 寫的 Cookie 信息
        • 當瀏覽器請求某網站時,會將瀏覽器存儲的跟網站相關的全部 Cookie 信息提交給網站服務器
      • 典型應用
        • 記住用戶名
        • 網站的廣告推送
      • 在 danjo 中,對 cookie 進行操做,須要一個 HttpResponse 或其子類的對象,相關函數以下:
        • set_cookie:設置Cookie信息

set_cookie(key, value='', max_age=None, expires=None)

  • cookie 是網站以鍵值對格式存儲在瀏覽器中的一段純文本信息,用於實現用戶跟蹤
  • max_age 是一個整數,表示在指定秒數後過時。
  • expires 是一個 datetime 或 timedelta 對象,會話將在這個指定的日期/時間過時
  • max_age 與 expires 二選一
  • 若是不指定過時時間,在關閉瀏覽器時 cookie 會過時。
  • delete_cookie(key):刪除指定的 key 的Cookie,若是 key 不存在則什麼也不發生。
  • 設置 cookie
    • 打開 booktest/views.py 文件,建立視圖 cookie_set

def cookie_set(request):

    response = HttpResponse("<h1>設置Cookie,請查看響應報文頭</h1>")

    response.set_cookie('h1', '你好')

    return response

  • 打開 booktest/urls.py 文件,配置 url

url(r'^cookie_set/$',views.cookie_set),

  • 在"開發者工具"中能夠在響應頭中查看到設置的 Cookie 信息
  • 讀取 cookie
    • Cookie 信息被包含在請求頭中,使用 request 對象的 COOKIES 屬性訪問
    • 打開booktest/views.py文件,建立視圖cookie_get

def cookie_get(request):

    response = HttpResponse("讀取Cookie,數據以下:<br>")

    if 'h1' in request.COOKIES:

        response.write('<h1>' + request.COOKIES['h1'] + '</h1>')

    return response

  • 打開 booktest/urls.py 文件,配置 url

url(r'^cookie_get/$',views.cookie_get),

  • 打開"開發者工具",在請求頭中能夠查看Cookie信息,瀏覽效果以下圖
  • Session
    • 對於敏感、重要的信息,建議要儲在服務器端,不能存儲在瀏覽器中,如用戶名、餘額、等級、驗證碼等信息。在服務器端進行狀態保持的方案就是Session
    • 啓用 Session
      • Django項目默認啓用Session
      • 打開 test3/settings.py文件,項 MIDDLEWARE_CLASSES 中爲啓用 Session 中間件
      • 禁用 session:將 session 中間件刪除便可
    • 存儲方式
      • 打開test3/settings.py文件,設置SESSION_ENGINE項指定Session數據存儲的方式,能夠存儲在數據庫、緩存、Redis等
      • 儲存在數據庫中,以下設置能夠寫,也可不寫,是默認的存儲方式

SESSION_ENGINE='django.contrib.sessions.backends.db'

  • 存儲在緩存中:存儲在本機內存中,若是丟失則不能找回,比數據庫的方式讀寫更快

SESSION_ENGINE='django.contrib.sessions.backends.cache' 

  • 混合存儲:優先從本機內存中存取,若是沒有則從數據庫中存取

SESSION_ENGINE='django.contrib.sessions.backends.cached_db' 

  • 若是存儲在數據庫中,須要在項INSTALLED_APPS中安裝Session應用
  • 遷移後會在數據庫中建立出儲存 Session 的表
  • 表結構以下圖
    • 由表結構可知,操做Session包括三個數據:鍵,值,過時時間
  • 依賴於 Cookie
    • 在使用 Session 後,會在 Cookie 中存儲一個 sessionid 的數據,每次請求時瀏覽器都會將這個數據發給服務器,服務器在接收到sessionid 後,會根據這個值找出這個請求者的 Session
    • 所以若是想使用Session,瀏覽器必須支持Cookie,不然就沒法使用Session了
    • 存儲Session時,鍵與Cookie中的sessionid相同,值是開發人員設置的鍵值對信息,進行了base64編碼,過時時間由開發人員設置
  • 對象及方法
    • 經過 HttpRequest 對象的 session 屬性進行會話的讀寫操做
    • 以鍵值對的格式寫session

request.session['']=

  • 根據鍵讀取值

request.session.get('',默認值) 

  • 清除全部session,在存儲中刪除值部分,保留 sessionid 和 {}

request.session.clear() 

  • 清除 session 數據,在存儲中刪除 session 的整條數據

request.session.flush()

  • 刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值

del request.session['']

  • 設置會話的超時時間,若是沒有指定過時時間則兩個星期後過時

request.session.set_expiry(value)

# 若是value是一個整數,會話將在value秒沒有活動後過時

# 若是value0,那麼用戶會話的Cookie將在用戶的瀏覽器關閉時過時

# 若是valueNone,那麼會話永不過時 

  • 示例
    • 寫 session
      • 打開booktest/views.py文件,建立視圖session_test

def session_test(request):

    request.session['h1']='hello'

    return HttpResponse('session') 

  • 打開booktest/urls.py文件,配置url

url(r'^session_test/$',views.session_test), 

  • 運行服務器,打開瀏覽器請求以下網址
  • 瀏覽效果以下圖,在"開發者工具"中能夠查看到響應頭中建立了 Cookie,裏面有個鍵爲 sessionid
  • 打開MySQL數據庫命令行,查詢數據以下圖
    • 查看Cookie中的sessionid值爲"l48euizwnd0u1vrq401rwc9yqxkj4ip4",數據表中session的鍵爲"l48euizwnd0u1vrq401rwc9yqxkj4ip4",是同樣的,這樣,服務器就能夠在衆多的請求者中找到對應的Session數據。
    • 在MySQL數據庫命令行中複製值,在Base64解碼中進行解碼查看以下圖
  • 讀 session
    • 打開booktest/views.py文件,修改session_test視圖以下

def session_test(request):

    # request.session['h1']='hello'

    h1=request.session.get('h1')

    return HttpResponse(h1) 

  • 刷新瀏覽器效果以下圖
  • 刪除
    • 打開booktest/views.py文件,修改session_test視圖以下

def session_test(request):

    # request.session['h1']='hello'

    # h1=request.session.get('h1')

    del request.session['h1']

    return HttpResponse('ok')

  

  • 刷新瀏覽器,在數據庫命令行中查詢,base64解碼後以下圖
  • 若是將全部的鍵及值都刪除,逐個調用del太麻煩,可使用clear()方法
  • 刪除 session
    • 打開booktest/views.py文件,修改session_test視圖以下:

def session_test(request):

    # request.session['h1']='hello'

    # h1=request.session.get('h1')

    # del request.session['h1']

    request.session.flush()

    return HttpResponse('ok') 

  • 刷新瀏覽器,在數據庫命令行中查詢以下圖
  • 相關操做
    • 關閉調試模式的方法
    • post 方法出現 403 Forbidden 時處理方法
  • 相關知識
    • 表單 form 提交參數的過程
      • 表單控件name屬性的值做爲鍵,value 屬性的值爲值,構成鍵值對提交
        • 若是表單控件沒有 name 屬性則不提交
        • 對於 checkbox 控件,name 屬性的值相同爲一組,被選中的項會被提交,出現一鍵多值的狀況
        • 鍵是表單控件 name 屬性的值,是由開發人員編寫的
        • 值是用戶填寫或選擇的
相關文章
相關標籤/搜索