Django的View(視圖)和路由系統

複製代碼
1、Django的View(視圖)
1、介紹
一個視圖函數(類),簡稱視圖,是一個簡單的Python 函數(類),它接受Web請求而且返回Web響應。
響應能夠是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文檔,或者一張圖片。
不管視圖自己包含什麼邏輯,都要返回響應。
代碼寫在哪裏也無所謂,只要它在你當前項目目錄下面。
你們約定俗成將視圖放置在項目(project)或應用程序(app)目錄中的名爲views.py的文件中。


2、FBV和CBV(Function Base View和Class Base View)
1. 基於函數的視圖:FBV
    視圖函數中經過request.method的不一樣進而執行不一樣的代碼

例如:
urls.py代碼
urlpatterns = [
    url(r'^login/', views.login),
]


views.py代碼
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        ret = UserInfo.objects.filter(username=username, pwd=pwd)
        if ret:
            return HttpResponse('登陸成功')
        else:
            return render(request, 'login.html')
    return render(request, 'login.html')
    
    
2. 基於類的視圖:CBV 1. 視圖類必須繼承django.views.View
    2. 在類中定義和請求方法同名的方法
    3. urls.py中註冊基於類的視圖的時候要區別於FBV要寫成:類名.as_view()

例如:
urls.py代碼
urlpatterns = [
    url(r'^login/', views.LoginView.as_view()),
]


views.py代碼
# 必須導入views 注意:不是本文件名稱
from django import views class LoginView(views.View): def get(self, request): return render(request, 'login.html') def post(self, request): username = request.POST.get('username') pwd = request.POST.get('pwd') ret = UserInfo.objects.filter(username=username, pwd=pwd) if ret: return HttpResponse('登陸成功') else: return render(request, 'login.html') 2、request對象 1、請求相關的經常使用值: path_info 返回用戶訪問url,不包括域名 method 請求中使用的HTTP方法的字符串表示,全大寫表示。 GET 包含全部HTTP GET參數的類字典對象 POST 包含全部HTTP POST參數的類字典對象 body 請求體,byte類型 request.POST的數據就是從body裏面提取到的 FILES 一個相似於字典的對象,包含全部的上傳文件信息。 例如:上面的登陸示例 在瀏覽器輸入:http://127.0.0.1:8000/login/?id=1 request.path_info --> login --> 只能取到url,取不到url的參數 request.path --> login --> 只能取到url,取不到url的參數 request.get_full_path() --> /login/?id=1 --> 能夠取到url和url參數 body 請求體,byte類型 request.POST的數據就是從body裏面提取到的 request.body 返回的是一個bytes類型的數據,是POST提交上來的數據,是沒有進行過修飾的數據,request.POST 的內容就是在request.body數據的基礎上進行分割組成的字典。 例如: request.body: b'csrfmiddlewaretoken=0o2Lc8UH2uhLbaKySq7j3gFm3afb8IBrfD6YHTUM7cD5KVSYtIlPcC7Vsx9xwcIx&username=zbj&pwd=123' request.POST: <QueryDict: {'csrfmiddlewaretoken': ['0o2Lc8UH2uhLbaKySq7j3gFm3afb8IBrfD6YHTUM7cD5KVSYtIlPcC7Vsx9xwcIx'], 'username': ['zbj'], 'pwd': ['123']}> 2、屬性 全部的屬性應該被認爲是隻讀的,除非另有說明。 屬性: django將請求報文中的請求行、頭部信息、內容主體封裝成 HttpRequest 類中的屬性。 除了特殊說明的以外,其餘均爲只讀的。
0.HttpRequest.scheme
   表示請求方案的字符串(一般爲http或https)

1.HttpRequest.body
    一個字符串,表明請求報文的主體。在處理非 HTTP 形式的報文時很是有用,例如:二進制圖片、XML,Json等。
    可是,若是要處理表單數據的時候,推薦仍是使用 HttpRequest.POST 。
    另外,咱們還能夠用 python 的類文件方法去操做它,詳情參考 HttpRequest.read() 。

 

2.HttpRequest.path
    一個字符串,表示請求的路徑組件(不含域名)。
    例如:"/music/bands/the_beatles/"



3.HttpRequest.method
    一個字符串,表示請求使用的HTTP 方法。必須使用大寫。
    例如:"GET""POST"

 

4.HttpRequest.encoding
    一個字符串,表示提交的數據的編碼方式(若是爲 None 則表示使用 DEFAULT_CHARSET 的設置,默認爲 'utf-8')。
    這個屬性是可寫的,你能夠修改它來修改訪問表單數據使用的編碼。
    接下來對屬性的任何訪問(例如從 GET 或 POST 中讀取數據)將使用新的 encoding 值。
    若是你知道表單數據的編碼不是 DEFAULT_CHARSET ,則使用它。

 

5.HttpRequest.GET 
    一個相似於字典的對象,包含 HTTP GET 的全部參數。詳情請參考 QueryDict 對象。

 

6.HttpRequest.POST
    一個相似於字典的對象,若是請求中包含表單數據,則將這些數據封裝成 QueryDict 對象。
    POST 請求能夠帶有空的 POST 字典 —— 若是經過 HTTP POST 方法發送一個表單,可是表單中沒有任何的數據,QueryDict 對象依然會被建立。
    所以,不該該使用 if request.POST  來檢查使用的是不是POST 方法;應該使用 if request.method == "POST" 
    另外:若是使用 POST 上傳文件的話,文件信息將包含在 FILES 屬性中。

 7.HttpRequest.COOKIES
    一個標準的Python 字典,包含全部的cookie。鍵和值都爲字符串。

 

8.HttpRequest.FILES
    一個相似於字典的對象,包含全部的上傳文件信息。
    FILES 中的每一個鍵爲<input type="file" name="" /> 中的name,值則爲對應的數據。
    注意,FILES 只有在請求的方法爲POST 且提交的<form> 帶有enctype="multipart/form-data" 的狀況下才會
    包含數據。不然,FILES 將爲一個空的相似於字典的對象。

 

9.HttpRequest.META
    一個標準的Python 字典,包含全部的HTTP 首部。具體的頭部信息取決於客戶端和服務器,下面是一些示例:

    CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。
    CONTENT_TYPE —— 請求的正文的MIME 類型。
    HTTP_ACCEPT —— 響應可接收的Content-Type。
    HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。
    HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。
    HTTP_HOST —— 客服端發送的HTTP Host 頭部。
    HTTP_REFERER —— Referring 頁面。
    HTTP_USER_AGENT —— 客戶端的user-agent 字符串。
    QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。
    REMOTE_ADDR —— 客戶端的IP 地址。
    REMOTE_HOST —— 客戶端的主機名。
    REMOTE_USER —— 服務器認證後的用戶。
    REQUEST_METHOD —— 一個字符串,例如"GET""POST"。
    SERVER_NAME —— 服務器的主機名。
    SERVER_PORT —— 服務器的端口(是一個字符串)。
   從上面能夠看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 以外,請求中的任何 HTTP 首部轉換爲 META 的鍵時,
    都會將全部字母大寫並將鏈接符替換爲下劃線最後加上 HTTP_  前綴。
    因此,一個叫作 X-Bender 的頭部將轉換成 META 中的 HTTP_X_BENDER 鍵。

 
10.HttpRequest.user
    一個 AUTH_USER_MODEL 類型的對象,表示當前登陸的用戶。
    若是用戶當前沒有登陸,user 將設置爲 django.contrib.auth.models.AnonymousUser 的一個實例。你能夠經過 is_authenticated() 區分它們。
    例如:
    if request.user.is_authenticated():
        # Do something for logged-in users.
    else:
        # Do something for anonymous users.
     

       user 只有當Django 啓用 AuthenticationMiddleware 中間件時纔可用。

     -------------------------------------------------------------------------------------

    匿名用戶
    class models.AnonymousUser

    django.contrib.auth.models.AnonymousUser 類實現了django.contrib.auth.models.User 接口,但具備下面幾個不一樣點:

    id 永遠爲None。
    username 永遠爲空字符串。
    get_username() 永遠返回空字符串。
    is_staff 和 is_superuser 永遠爲False。
    is_active 永遠爲 False。
    groups 和 user_permissions 永遠爲空。
    is_anonymous() 返回True 而不是False。
    is_authenticated() 返回False 而不是True。
    set_password()、check_password()、save() 和delete() 引起 NotImplementedError。
    New in Django 1.8:
    新增 AnonymousUser.get_username() 以更好地模擬 django.contrib.auth.models.User。

 

11.HttpRequest.session
    一個既可讀又可寫的相似於字典的對象,表示當前的會話。只有當Django 啓用會話的支持時纔可用。
    完整的細節參見會話的文檔。
屬性
 
  

 

3、上傳文件示例
注意:form表單提交的時候,enctype默認是application/x-www-form-urlencoded這個編碼形式, 即便用鍵值對的形式POST數據,在只有文本數據提交時使用。 而若是POST請求中有文件類型的數據,則需指定 enctype="multipart/form-data" 代表POST的數據中 既有文本類型數據(鍵值對傳輸數據)也有文件類型數據(二進制傳輸數據)。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-type" charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Upload</title>
</head>

<body>

<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <p><input type="text" name="username"></p>
    <p><input type="file" name="file"></p>
    <p><input type="submit"></p>
</form>

</body>
</html>
upload.html
 
  
from django.shortcuts import render, HttpResponse, redirect
from django import views
import os, time
from django.conf import settings

class UploadView(views.View):

    def get(self, request):
        return render(request, 'upload.html')

    def post(self, request):
        # 文本類型的數據用request.POST獲取,鍵對應的值是字符串類型
        print(request.POST)
        # 文件類型的數據用request.FILES獲取,鍵對應的值是類的對象
        print(request.FILES)
        # 獲取文件對象(是一大串bytes類型的字節碼)
        file_obj = request.FILES.get('file')
        # 文件對象有個內置的屬性name,用於獲取接收到的文件名
        filename = file_obj.name
        # 判斷本地是否有同名的文件存在
        if os.path.exists(os.path.join(settings.BASE_DIR, filename)):
            # 重命名文件
            prefix_name = filename.split('.')[0]  # 前綴
            suffix_name = filename.split('.')[1]  # 後綴
            filename = prefix_name + str(time.time()) + suffix_name
        # 建一個同名的文件接收上傳的數據
        # with open(filename, 'wb') as f:
        #     for i in file_obj:
        #         f.write(i)

        # 跟上面的方法是同樣的,只不過chunks是一個內置的方法,能夠設置每次接收的數據大小
        with open(filename, 'wb') as f:
            for chunk in file_obj.chunks(chunk_size=1024):
                f.write(chunk)

        return HttpResponse('收到啦!')
views.py

 

 注意:
request.POST.get('xxx')      # 取到name爲xxx這個值
request.POST.getlist('xxx')  # 取到name爲xxx這個列表(用於checkbox和多選的select)

request.FILES.get('xxx')     # 取到name爲xxx的某個上傳文件的對象
request.FILES.getlist('xxx') # 取到name爲xxx的多選的上傳文件的對象列表 <input type='file' multiple>


4、方法
1.HttpRequest.get_host()

  根據從HTTP_X_FORWARDED_HOST(若是打開 USE_X_FORWARDED_HOST,默認爲False)和 HTTP_HOST 頭部信息返回請求的原始主機。
   若是這兩個頭部沒有提供相應的值,則使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有詳細描述。

  USE_X_FORWARDED_HOST:一個布爾值,用於指定是否優先使用 X-Forwarded-Host 首部,僅在代理設置了該首部的狀況下,才能夠被使用。

  例如:"127.0.0.1:8000"

  注意:當主機位於多個代理後面時,get_host() 方法將會失敗。除非使用中間件重寫代理的首部。

 

2.HttpRequest.get_full_path()

  返回 path,若是能夠將加上查詢字符串。

  例如:"/music/bands/the_beatles/?print=true"

 

3.HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

  返回簽名過的Cookie 對應的值,若是簽名再也不合法則返回django.core.signing.BadSignature。

  若是提供 default 參數,將不會引起異常並返回 default 的值。

  可選參數salt 能夠用來對安全密鑰強力攻擊提供額外的保護。max_age 參數用於檢查Cookie 對應的時間戳以確保Cookie 的時間不會超過max_age 秒。

        >>> request.get_signed_cookie('name')
        'Tony'
        >>> request.get_signed_cookie('name', salt='name-salt')
        'Tony' # 假設在設置cookie的時候使用的是相同的salt
        >>> request.get_signed_cookie('non-existing-cookie')
        ...
        KeyError: 'non-existing-cookie'    # 沒有相應的鍵時觸發異常
        >>> request.get_signed_cookie('non-existing-cookie', False)
        False
        >>> request.get_signed_cookie('cookie-that-was-tampered-with')
        ...
        BadSignature: ...    
        >>> request.get_signed_cookie('name', max_age=60)
        ...
        SignatureExpired: Signature age 1677.3839159 > 60 seconds
        >>> request.get_signed_cookie('name', False, max_age=60)
        False
         


4.HttpRequest.is_secure()

  若是請求時是安全的,則返回True;即請求通是過 HTTPS 發起的。

 

5.HttpRequest.is_ajax()

  若是請求是經過XMLHttpRequest 發起的,則返回True,方法是檢查 HTTP_X_REQUESTED_WITH 相應的首部是不是字符串'XMLHttpRequest'。

  大部分現代的 JavaScript 庫都會發送這個頭部。若是你編寫本身的 XMLHttpRequest 調用(在瀏覽器端),你必須手工設置這個值來讓 is_ajax() 能夠工做。

  若是一個響應須要根據請求是不是經過AJAX 發起的,而且你正在使用某種形式的緩存例如Django 的 cache middleware, 
   你應該使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 裝飾你的視圖以讓響應可以正確地緩存。
方法
 
  

3、Response對象
1、介紹 與由Django自動建立的HttpRequest對象相比,HttpResponse對象是咱們的職責範圍了。咱們寫的每一個視圖都須要實例化,填充和返回一個HttpResponse。 2、使用 傳遞字符串 from django.shortcuts import HttpResponse response = HttpResponse("Here's the text of the Web page.") response = HttpResponse("Text only, please.", content_type="text/plain") 設置或刪除響應頭信息 response = HttpResponse() response['Content-Type'] = 'text/html; charset=UTF-8' del response['Content-Type'] 3、屬性 HttpResponse.content:響應內容 HttpResponse.charset:響應內容的編碼 HttpResponse.status_code:響應的狀態碼 4、JsonResponse對象 JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應。 1、使用HttpResponse返回字典 def json_data(request): d = {"name": "小明", "age": 24} import json str_d = json.dumps(d, ensure_ascii=False) return HttpResponse(str_d, content_type='application/json') 2、使用JsonResponse 上面的代碼等於: def json_data(request): d = {"name": "小明", "age": 24} from django.http import JsonResponse # 導入JsonResponse return JsonResponse(d) 注意:JsonResponse通常用於返回字典的Json序列化,列表通常不推薦使用, 若是你死皮賴臉就是想要返回列表,那麼就須要添加safe=False參數 def json_data(request): l = ["a", "b", "c"] from django.http import JsonResponse return JsonResponse(l, safe=False) 5、render 結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。 參數: request: 用於生成響應的請求對象。 template_name:要使用的模板的完整名稱,可選的參數 context:添加到模板上下文的一個字典。默認是一個空字典。若是字典中的某個值是可調用的,視圖將在渲染模板以前調用它。 content_type:生成的文檔要使用的MIME類型。默認爲 DEFAULT_CONTENT_TYPE 設置的值。默認爲'text/html' status:響應的狀態碼。默認爲200。 useing: 用於加載模板的模板引擎的名稱。 例子: from django.shortcuts import render def my_view(request): # 視圖的代碼寫在這裏 return render(request, 'myapp/index.html', {'foo': 'bar'}) 上面的代碼等於: from django.shortcuts import HttpResponse from django.template import loader def my_view(request): # 視圖代碼寫在這裏 t = loader.get_template('myapp/index.html') c = {'foo': 'bar'} return HttpResponse(t.render(c, request)) 6、redirect 參數能夠是: 一個模型:將調用模型的get_absolute_url() 函數 一個視圖,能夠帶有參數:將使用urlresolvers.reverse 來反向解析名稱 一個絕對的或相對的URL,將原封不動的做爲重定向的位置。 默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。 示例: 你能夠用多種方式使用redirect() 函數。 1、傳遞一個具體的ORM對象 將調用具體ORM對象的get_absolute_url() 方法來獲取重定向的URL: from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object) 2、傳遞一個視圖的名稱 def my_view(request): ... return redirect('some-view-name', foo='bar') 3、傳遞要重定向到的一個具體的網址 def my_view(request): ... return redirect('/some/url/') 4、一個完整的網址 def my_view(request): ... return redirect('http://example.com/') 5、默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向: def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True) 臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來講是沒什麼區別的,它主要面向的是搜索引擎的機器人。 A頁面臨時重定向到B頁面,那搜索引擎收錄的就是A頁面。 A頁面永久重定向到B頁面,那搜索引擎收錄的就是B頁面。 7、路由系統 1、URLconf配置 基本格式(django1.x版本):參數都是字符串類型的 from django.conf.urls import url urlpatterns = [ url(正則表達式, views視圖函數,參數,別名), ] Django 2.0版本中的路由系統已經替換成下面的寫法:參數支持整型 from django.urls import path urlpatterns = [ path('articles/2003/', views.special_case_2003), path('articles/<int:year>/', views.year_archive), path('articles/<int:year>/<int:month>/', views.month_archive), path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), ] 參數說明: 正則表達式:一個正則表達式字符串 views視圖函數:一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串 參數:可選的要傳遞給視圖函數的默認參數(字典形式) 別名:一個可選的name參數 擴展:若是想在django2.x版本使用1.x版本的代碼 from django.urls import re_path urlpatterns = [ re_path(正則表達式, views視圖函數,參數,別名), ] 2、正則表達式詳解 基本配置: from django.conf.urls import url from appname import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ] 注意事項: urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表達式,一旦匹配成功則再也不繼續。 若要從URL中捕獲一個值,只須要在它周圍放置一對圓括號(分組匹配)。 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。 每一個正則表達式前面的'r' 是可選的可是建議加上。 補充說明: # 是否開啓URL訪問地址後面不爲/跳轉至帶有/的路徑的配置項 APPEND_SLASH=True Django settings.py配置文件中默認沒有 APPEND_SLASH 這個參數,但 Django 默認這個參數爲 APPEND_SLASH = True。 其做用就是自動在網址結尾加'/'。 其效果就是: 咱們定義了urls.py: from django.conf.urls import url from appname import views urlpatterns = [ url(r'^blog/$', views.blog), ] 訪問 http://www.example.com/blog 時,默認將網址自動轉換爲 http://www.example/com/blog/ 。 若是在settings.py中設置了 APPEND_SLASH=False,此時咱們再請求 http://www.example.com/blog 時就會提示找不到頁面。 3、分組命名匹配 上面的示例使用簡單的正則表達式分組匹配(經過圓括號)來捕獲URL中的值並以位置參數形式傳遞給視圖。 在更高級的用法中,可使用分組命名匹配的正則表達式組來捕獲URL中的值並以關鍵字參數形式傳遞給視圖。 在Python的正則表達式中,分組命名正則表達式組的語法是(?P<name>pattern),其中name是組的名稱,pattern是要匹配的模式。 Django路由系統匹配URL路徑的時候是從上到下按照註冊順序來的 Django的路由系統只匹配URL路徑,不匹配域名、端口、URL參數 注意:分組匹配和分組命名匹配不能混合使用!!! url(r'^book/(?P<yyyy>[0-9]{4})/([0-9]{2})/$', views.book) # 錯誤的 3-1、圓括號獲取URL中的值並以位置參數形式傳遞給視圖 urlpatterns = [ url(r'^book/([0-9]{4})/$', views.book), # 這裏([0-9]{4})獲取到的值會當成位置參數傳遞給views.book ] 因此views.book定義的時候應該要定義多一個形參用來接收匹配到的實參 def book(request, year): print(year) return HttpResponse('book') 3-二、分組命名(?P<name>)匹配的正則表達式組來捕獲URL中的值並以關鍵字參數形式傳遞給視圖。 urlpatterns = [ url(r'^book/(?P<yyyy>[0-9]{4})/$', views.book), # 這裏([0-9]{4})獲取到的值會當成關鍵字參數傳遞給views.book ] 因此views.book定義的時候應該要定義多一個關鍵字參數yyyy用來接收匹配到的實參 def book(request, yyyy): # 只能使用yyyy接收,由於是關鍵字傳參 print(yyyy) return HttpResponse('book') 3-3、URLconf匹配的位置 URLconf 在請求的URL 上查找,將它當作一個普通的Python 字符串。不包括GET和POST參數以及域名。 例如,http://www.example.com/myapp/ 請求中,URLconf 將查找myapp/。 在http://www.example.com/myapp/?page=3 請求中,URLconf 仍將查找myapp/。 URLconf 不檢查請求的方法。換句話講,全部的請求方法 —— 同一個URL的POST、GET、HEAD等等 —— 都將路由到相同的函數。 3-4、捕獲的參數永遠都是字符串 每一個在URLconf中捕獲的參數都做爲一個普通的Python字符串傳遞給視圖,不管正則表達式使用的是什麼匹配方式。例如,下面這行URLconf 中: url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), 傳遞到視圖函數views.year_archive() 中的year 參數永遠是一個字符串類型。 3-五、視圖函數中指定默認值 # urls.py中 urlpatterns = [ url(r'^blog/$', views.blog), url(r'^blog/(?P<num>\d+)/$', views.blog), ] # views.py中,能夠爲num指定默認值 def blog(request, num='1'): print(num, type(num)) return HttpResponse('blog') 在上面的例子中,兩個URL模式指向相同的view - blog 可是第一個模式並無從URL中捕獲任何東西。 若是第一個模式匹配上了,blog()函數將使用其默認參數num=「1」,若是第二個模式匹配,blog()將使用正則表達式捕獲到的num值。 3-6、include其餘的URLconfs(二級路由系統) 建立兩個app,每一個app都建立一個urls.py # 項目的urls.py from django.conf.urls import url, include from app01 import urls as app01_urls from app02 import urls as app02_urls urlpatterns = [ # 二級路由系統 url(r'^app01/', include(app01_urls)), url(r'^app02/', include(app02_urls)), ] # app01的urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^book/$', views.book_list), url(r'^book/(?P<yyyy>[0-9]{4})/$', views.book), url(r'^blog/$', views.blog), url(r'^blog/(?P<num>\d+)/$', views.blog), ] # app02的urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/$', views.index), url(r'^home/$', views.home), ] 解析:在瀏覽器輸入http://127.0.0.1:8000/app02/home/ 首先會拿着app02/home/去項目的urls中匹配,找到url(r'^app02/', include(app02_urls)), 看到include,就拿着home/去app02的urls中匹配,找到url(r'^home/$', views.home),就訪問home頁面。 4、傳遞額外的參數給視圖函數 URLconfs 具備一個鉤子,讓你傳遞一個Python 字典做爲額外的參數傳遞給視圖函數。 django.conf.urls.url() 函數能夠接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。 例如: urlpatterns = [ url(r'^blog/(?P<num>\d+)/$', views.blog, {'author': '明哥'}), ] def blog(request, num, author): print(num, type(num)) print(author) return HttpResponse('blog') 在這個例子中,對於/blog/2/請求,Django 將調用views.blog(request, num='2', author='明哥') 這個技術在Syndication 框架中使用,來傳遞元數據和選項給視圖。 8、命名URL和URL反向解析 在最終的路由那裏設置name屬性,給這個路由設置別名, 而後在視圖函數那裏導入from django.urls import reverse, 在須要解析地址的地方使用reverse(別名),就能夠解析出這個url, 且不管路由自己的地址如何改變,只要使用reverse(別名),同樣能解析出url地址 例如: # 項目的urls.py from django.conf.urls import url, include from app02 import urls as app02_urls urlpatterns = [ # 二級路由系統 url(r'^app02/', include(app02_urls)), ] # app02的urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^login/$', views.login), url(r'^index/$', views.index, name='myindex'), ] 一、在views.py中使用 # views.py from django.shortcuts import render, redirect, HttpResponse from django.urls import reverse # 導入reverse反向解析出地址 def login(request): if request.method == 'POST': username = request.POST.get('username') pwd = request.POST.get('pwd') ret = UserInfo.objects.filter(username=username, pwd=pwd) if ret: return redirect(reverse('myindex')) # reverse反向解析出url地址:/app02/index/ return render(request, 'login.html') def index(request): return HttpResponse('index') 解析:在瀏覽器輸入http://127.0.0.1:8000/app02/login/,進入登陸界面, 登陸成功後,redirect(reverse('myindex')),reverse會根據別名myindex自動解析出index的具體路徑(http://127.0.0.1:8000/app02/index/), 並且不管index的具體路由怎麼改變,reverse('myindex')老是能解析出具體的url。 注意:當url須要參數時: 1.若是index須要傳位置參數: urlpatterns = [ url(r'^index/(\d+)/$', views.index, name='myindex'), ] return redirect(reverse('myindex', args=('2018',))) 2.若是index須要傳關鍵字參數: urlpatterns = [ url(r'^index/(?P<year>\d+)/$', views.index, name='myindex'), ] return redirect(reverse('myindex', kwargs={'year': '2019'})) 2、在HTML模板中使用 無參數:<a href="{% url 'myindex' %}">myindex</a> 有參數:<a href="{% url 'myindex' '2018' %}">myindex</a> 9、命名空間模式 若是不一樣的APP使用了相同的URL反轉名稱,那麼reverse怎麼解析? 使用命名空間模式(namespace)能夠解決這個問題,即不一樣的APP使用相同的URL名稱,URL的命名空間模式也可讓你惟一反轉命名的URL。 例如: # 項目中的urls.py from django.conf.urls import url, include urlpatterns = [ url(r'^app01/', include('app01.urls', namespace='app01')), url(r'^app02/', include('app02.urls', namespace='app02')), ] # app01中的urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/(?P<year>\d+)/$', views.index, name='myindex'), ] # app02中的urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/(?P<year>\d+)/$', views.index, name='myindex'), ] 如今,兩個app中url的別名重複了,反轉URL的時候就能夠經過命名空間的名稱獲得我當前的URL。 語法: '命名空間名稱:URL名稱' # 在HTML模板中使用: <a href="{% url 'app01:myindex' '2018' %}">app01 myindex</a> <a href="{% url 'app02:myindex' '2019' %}">app02 myindex</a> # 在views中的函數中使用 v = reverse('app01:myindex', kwargs={'year':2018}) v = reverse('app02:myindex', kwargs={'year':2019}) 這樣即便app中URL的命名相同,我也能夠反轉獲得正確的URL了。
複製代碼
相關文章
相關標籤/搜索