1. 程式人生 > >Django筆記--視圖

Django筆記--視圖

OS mime 上下文 day .get mes handle encoding ear

URLconf
  在settings.py文件中通過ROOT_URLCONF指定根級url的配置
  urlpatterns是一個url()實例的列表
  一個url()對象包括:
    正則表達式
    視圖函數
    名稱name
  編寫URLconf的註意:
    若要從url中捕獲一個值,需要在它周圍設置一對圓括號
    不需要添加一個前導的反斜杠,如應該寫作‘test/‘,而不應該寫作‘/test/‘
    每個正則表達式前面的r表示字符串不轉義
  請求的url被看做是一個普通的python字符串,進行匹配時不包括get或post請求的參數及域名
      http://www.itcast.cn/python/1/?i=1&p=new,只匹配“/python/1/”部分
  正則表達式非命名組,通過位置參數傳遞給視圖
      url(r‘^([0-9]+)/$‘, views.detail, name=‘detail‘),
  正則表達式命名組,通過關鍵字參數傳遞給視圖,本例中關鍵字參數為id
      url(r‘^(?P<id>[0-9]+)/$‘, views.detail, name=‘detail‘),
  參數匹配規則:優先使用命名參數,如果沒有命名參數則使用位置參數
  每個捕獲的參數都作為一個普通的python字符串傳遞給視圖
  性能:urlpatterns中的每個正則表達式在第一次訪問它們時被編譯,這使得系統相當快

包含其它的URLconfs


  在應用中創建urls.py文件,定義本應用中的urlconf,再在項目的settings中使用include()

from django.conf.urls import include, url
urlpatterns = [
url(r^, include(booktest.urls, namespace=booktest)),
]

  匹配過程:先與主URLconf匹配,成功後再用剩余的部分與應用中的URLconf匹配
      請求http://www.itcast.cn/booktest/1/
      在sesstings.py中的配置:
      url(r‘^booktest/‘, include(‘booktest.urls‘, namespace=‘booktest‘)),
      在booktest應用urls.py中的配置
      url(r‘^([0-9]+)/$‘, views.detail, name=‘detail‘),
      匹配部分是:/booktest/1/
      匹配過程:在settings.py中與“booktest/”成功,再用“1/”與booktest應用的urls匹配
  使用include可以去除urlconf的冗余
  參數:視圖會收到來自父URLconf、當前URLconf捕獲的所有參數
  在include中通過namespace定義命名空間,用於反解析

URL的反向解析(給URL起名字)
  如果在視圖、模板中使用硬編碼的鏈接,在urlconf發生改變時,維護是一件非常麻煩的事情
  解決:在做鏈接時,通過指向urlconf的名稱,動態生成鏈接地址
  視圖:使用django.core.urlresolvers.reverse()函數
  模板:使用url模板標簽

定義視圖
  本質就是一個函數
  視圖的參數
    一個HttpRequest實例
    通過正則表達式組獲取的位置參數
    通過正則表達式組獲得的關鍵字參數
  在應用目錄下默認有views.py文件,一般視圖都定義在這個文件中
  如果處理功能過多,可以將函數定義到不同的py文件中,建議在功能劃分的時候就定義好,把不同的功能劃分獨立成不同的APP,便於日後的維護。

錯誤視圖


  Django原生自帶幾個默認視圖用於處理HTTP錯誤
  404 (page not found) 視圖
      defaults.page_not_found(request, template_name=‘404.html‘)
      默認的404視圖將傳遞一個變量給模板:request_path,它是導致錯誤的URL
      如果Django在檢測URLconf中的每個正則表達式後沒有找到匹配的內容也將調用404視圖
      如果在settings中DEBUG設置為True,那麽將永遠不會調用404視圖,而是顯示URLconf 並帶有一些調試信息。如果將DEBUG設置為False,還要把setting中的ALLOWED_HOSTS改為[‘*‘,],允許所有的IP地址訪問。
      在templates中創建404.html
  500 (server error) 視圖
      defaults.server_error(request, template_name=‘500.html‘)
      在視圖代碼中出現運行時錯誤
      默認的500視圖不會傳遞變量給500.html模板
      如果在settings中DEBUG設置為True,那麽將永遠不會調用505視圖,而是顯示URLconf 並帶有一些調試信息,如果將DEBUG設置為False,還要把setting中的ALLOWED_HOSTS改為[‘*‘,],允許所有的IP地址訪問。
  400 (bad request) 視圖
      defaults.bad_request(request, template_name=‘400.html‘)
      錯誤來自客戶端的操作
      當用戶進行的操作在安全方面可疑的時候會調用該視圖,例如篡改會話cookie

HttpReqeust對象
  服務器接收到http協議的請求後,會根據報文創建HttpRequest對象
  視圖函數的第一個參數是HttpRequest對象
  在django.http模塊中定義了HttpRequest對象的API

  屬性
    下面除非特別說明,屬性都是只讀的
    path:一個字符串,表示請求的頁面的完整路徑,不包含域名
    method:一個字符串,表示請求使用的HTTP方法,常用值包括:‘GET‘、‘POST‘
    encoding:一個字符串,表示提交的數據的編碼方式,如果為None則表示使用瀏覽器的默認設置,一般為utf-8。這個屬性是可寫的,可以通過修改它來修改訪問表單數據使用的編碼,接下來對屬性的任何訪問將使用新的encoding值
    GET:一個類似於字典(但不是字典)的對象,包含get請求方式的所有參數
    POST:一個類似於字典的對象,包含post請求方式的所有參數
    FILES:一個類似於字典的對象,包含所有的上傳文件
    COOKIES:一個標準的Python字典,包含所有的cookie,鍵和值都為字符串
    session:一個既可讀又可寫的類似於字典的對象,表示當前的會話,只有當Django 啟用會話的支持時才可用,詳細內容見“狀態保持”
  方法
    is_ajax():如果請求是通過XMLHttpRequest發起的,則返回True

QueryDict對象
    定義在django.http.QueryDict
    request對象的屬性GET、POST都是QueryDict類型的對象
    與python字典不同,QueryDict類型的對象用來處理同一個鍵帶有多個值的情況

    方法get():根據鍵獲取值
      只能獲取鍵的一個值
      如果一個鍵同時擁有多個值,獲取最後一個值
      dict.get(‘鍵‘,default)或簡寫為dict[‘鍵‘]

    方法getlist():根據鍵獲取值
      將鍵的值以列表返回,可以獲取一個鍵的多個值
      dict.getlist(‘鍵‘,default)

GET屬性
    QueryDict類型的對象
    包含get請求方式的所有參數
    與url請求地址中的參數對應,位於?後面
    參數的格式是鍵值對,如key1=value1
    多個參數之間,使用&連接,如key1=value1&key2=value2
    鍵是開發人員定下來的,值是可變的

POST屬性
    QueryDict類型的對象
    包含post請求方式的所有參數
    與form表單中的控件對應
      問:表單中哪些控件會被提交?
      答:控件要有name屬性,則name屬性的值為鍵,value屬性的值為鍵,構成鍵值對提交
      對於checkbox控件,name屬性一樣為一組,當控件被選中後會被提交,存在一鍵多值的情況
    一鍵一值可以用 uname=request.POST[‘uname‘] 或者 uname=request.POST.get(‘uname‘)
    一鍵多值需要用 uhobby=request.POST.getlist(‘uhobby‘)
    鍵是開發人員定下來的,值是可變的

HttpResponse對象
    在django.http模塊中定義了HttpResponse對象的API
    HttpRequest對象由Django自動創建,HttpResponse對象由程序員創建

    不調用模板,直接返回數據

#coding=utf-8
from django.http import HttpResponse

def index(request):
return HttpResponse(你好)

    調用模板
      分為兩步:加載模板,渲染模板

from django.http import HttpResponse
from django.template import RequestContext, loader

def index(request):
t1 = loader.get_template(polls/index.html)
context = RequestContext(request, {h1: hello})
return HttpResponse(t1.render(context))

    屬性
      content:表示返回的內容,字符串類型
      charset:表示response采用的編碼字符集,字符串類型
      status_code:響應的HTTP響應狀態碼
      content-type:指定輸出的MIME類型

    方法
      init :使用頁內容實例化HttpResponse對象
      write(content):以文件的方式寫
      flush():以文件的方式輸出緩存區
      set_cookie(key, value=‘‘, max_age=None, expires=None):設置Cookie
        key、value都是字符串類型
        max_age是一個整數,表示在指定秒數後過期
        expires是一個datetime或timedelta對象,會話將在這個指定的日期/時間過期,註意datetime和timedelta值只有在使用PickleSerializer時才可序列化
        max_age與expires二選一
        如果不指定過期時間,則兩個星期後過期
        跨域名不可共享cookie信息
      delete_cookie(key):刪除指定的key的Cookie,如果key不存在則什麽也不發生

    子類HttpResponseRedirect
      重定向,服務器端跳轉
      構造函數的第一個參數用來指定重定向的地址

    子類JsonResponse
      返回json數據,一般用於異步請求
      _init _(data)
      幫助用戶創建JSON編碼的響應
      參數data是字典對象
      JsonResponse的默認Content-Type為application/json

簡寫函數
  render
      render(request, template_name[, context])
      結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的HttpResponse對象
      request:該request用於生成response
      template_name:要使用的模板的完整名稱
      context:添加到模板上下文的一個字典,視圖將在渲染模板之前調用它

from django.shortcuts import render

def index(request):
return render(request, booktest/index.html, {h1: hello})

  重定向
      redirect(to)
      為傳遞進來的參數返回HttpResponseRedirect
      to推薦使用反向解析

from django.shortcuts import redirect
from django.core.urlresolvers import reverse

def index(request):
return redirect(reverse(booktest:index2))

  得到對象或返回404
      get_object_or_404(klass, args, *kwargs)
      通過模型管理器或查詢集調用get()方法,如果沒找到對象,不引發模型的DoesNotExist異常,而是引發Http404異常
      klass:獲取對象的模型類、Manager對象或QuerySet對象
      **kwargs:查詢的參數,格式應該可以被get()和filter()接受
      如果找到多個對象將引發MultipleObjectsReturned異常

from django.shortcuts import *

def detail(request, id):
try:
book = get_object_or_404(BookInfo, pk=id)
except BookInfo.MultipleObjectsReturned:
book = None
return render(request, booktest/detail.html, {book: book})

  得到列表或返回404
      get_list_or_404(klass, args, *kwargs)
      klass:獲取列表的一個Model、Manager或QuerySet實例
      **kwargs:查尋的參數,格式應該可以被get()和filter()接受

from django.shortcuts import *

def index(request):
# list = get_list_or_404(BookInfo, pk__lt=1)
list = get_list_or_404(BookInfo, pk__lt=6)
return render(request, booktest/index.html, {list: list})

狀態保持
    http協議是無狀態的:每次請求都是一次新的請求,不會記得之前通信的狀態
    客戶端與服務器端的一次通信,就是一次會話
    實現狀態保持的方式:在客戶端或服務器端存儲與會話有關的數據
    存儲方式包括cookie、session,會話一般指session對象
    使用cookie,所有數據存儲在客戶端,註意不要存儲敏感信息
    推薦使用sesison方式,所有數據存儲在服務器端,在客戶端cookie中存儲session_id
    狀態保持的目的是在一段時間內跟蹤請求者的狀態,可以實現跨頁面訪問當前請求者的數據
    註意:不同的請求者之間不會共享這個數據,與請求者一一對應

    啟用session
      使用django-admin startproject創建的項目默認啟用
      在settings.py文件中
      項INSTALLED_APPS列表中添加:
        ‘django.contrib.sessions‘,

      項MIDDLEWARE_CLASSES列表中添加:
        ‘django.contrib.sessions.middleware.SessionMiddleware‘,
      禁用會話:刪除上面指定的兩個值,禁用會話將節省一些性能消耗

    使用session
      啟用會話後,每個HttpRequest對象將具有一個session屬性,它是一個類字典對象
      get(key, default=None):根據鍵獲取會話的值
      clear():清除所有會話
      flush():刪除當前的會話數據並刪除會話的Cookie
      del request.session[‘member_id‘]:刪除會話

from django.shortcuts import render, redirect
from django.core.urlresolvers import reverse

//通過用戶登錄聯系session
def session1(request):
uname = request.session.get(uname)    //盡量不要采取uname = request.session[uname]這樣的方式,因為如果uname這個鍵不存在的話,會跳出異常,而用uname = request.session.get(uname)這樣的方式,即使uname不存在,也只是返回空而已,不會報異常
context = {uname: uname}
return render(request, booktest/session1.html, context)

def session2(request):
return render(request, booktest/session2.html)

def session2_handle(request):
uname = request.POST[uname]
request.session[uname] = uname
return redirect(reverse(/booktest/session1))

def session3(request):
//刪除session
del request.session[uname]
return redirect(/booktest/session1)

    會話過期時間
      set_expiry(value):設置會話的超時時間
      如果沒有指定,則兩個星期後過期
      如果value是一個整數,會話將在values秒沒有活動後過期
      若果value是一個imedelta對象,會話將在當前時間加上這個指定的日期/時間過期
      如果value為0,那麽用戶會話的Cookie將在用戶的瀏覽器關閉時過期
      如果value為None,那麽會話永不過期

def login_handle(request):
request.session[uname] = request.POST[uname]
# request.session.set_expiry(10)
# request.session.set_expiry(timedelta(days=5))
# request.session.set_expiry(0)
# request.session.set_expiry(None)
return redirect(reverse(main:index))

    存儲session
      使用存儲會話的方式,可以使用settings.py的SESSION_ENGINE項指定
      基於數據庫的會話:這是django默認的會話存儲方式,需要添加django.contrib.sessions到的INSTALLED_APPS設置中,運行manage.py migrate在數據庫中安裝會話表,可顯示指定為
        SESSION_ENGINE=‘django.contrib.sessions.backends.db‘
      基於緩存的會話:只存在本地內存中,如果丟失則不能找回,但比數據庫的方式讀寫更快
        SESSION_ENGINE=‘django.contrib.sessions.backends.cache‘
      ☆可以將緩存和數據庫同時使用:優先從本地緩存中獲取,如果沒有則從數據庫中獲取
        SESSION_ENGINE=‘django.contrib.sessions.backends.cached_db‘
      Django中session的存儲默認采用base64加密

    使用Redis緩存session
      會話還支持文件、純cookie、Memcached、Redis等方式存儲,下面演示使用redis存儲
        安裝包
          pip install django-redis-sessions
        修改settings中的配置,增加如下項

SESSION_ENGINE = redis_sessions.session
SESSION_REDIS_HOST = localhost
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0
SESSION_REDIS_PASSWORD = ‘‘
SESSION_REDIS_PREFIX = session

        管理redis的命令
          啟動:sudo redis-server /etc/redis/redis.conf
          停止:sudo redis-server stop
          重啟:sudo redis-server restart
          redis-cli:使用客戶端連接服務器
          keys *:查看所有的鍵
          get name:獲取指定鍵的值
          del name:刪除指定名稱的鍵

Django筆記--視圖