1. 程式人生 > >Django路由配置系統,檢視函式

Django路由配置系統,檢視函式

一、路由配置系統(URLconf)

URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要為該URL呼叫的檢視函式之間的對映表;你就是以這種方式告訴Django,對於這個URL呼叫這段程式碼,對於那個URL呼叫那段程式碼。

    '''

urlpatterns = [
url(正則表示式, views檢視函式,引數,別名),
]


引數說明:

一個正則表示式字串
一個可呼叫物件,通常為一個檢視函式或一個指定檢視函式路徑的字串
可選的要傳遞給檢視函式的預設引數(字典形式)
一個可選的name引數

'''

 

1、URLconf的正則字串引數

1.1 簡單配置

from django.conf.urls import url

from . 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),
]
'''
    NOTE:
一旦匹配成功則不再繼續
若要從URL 中捕獲一個值,只需要在它周圍放置一對圓括號。
不需要新增一個前導的反斜槓,因為每個URL 都有。例如,應該是^articles 而不是 ^/articles。
每個正則表示式前面的'r' 是可選的但是建議加上。

一些請求的例子:

    /articles/2005/3/ 不匹配任何URL 模式,因為列表中的第三個模式要求月份應該是兩個數字。
    /articles/2003/ 將匹配列表中的第一個模式不是第二個,因為模式按順序匹配,第一個會首先測試是否匹配。
    /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將呼叫函式
                       views.month_archive(request, '2005', '03')。
    '''

1.2 有名分組(named group)

上面的示例使用簡單的、沒有命名的正則表示式組(通過圓括號)來捕獲URL 中的值並以位置 引數傳遞給檢視。在更高階的用法中,可以使用命名的正則表示式組來捕獲URL 中的值並以關鍵字 引數傳遞給檢視。

在Python 正則表示式中,命名正則表示式組的語法是(?P<name>pattern),其中name 是組的名稱,pattern 是要匹配的模式。

下面是以上URLconf 使用命名組的重寫:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

這個實現與前面的示例完全相同,只有一個細微的差別:捕獲的值作為關鍵字引數而不是位置引數傳遞給檢視函式。例如:

  /articles/2005/03/    
    請求將呼叫views.month_archive(request, year='2005', month='03')函式
    /articles/2003/03/03/ 
    請求將呼叫函式views.article_detail(request, year='2003', month='03', day='03')。

在實際應用中,這意味你的URLconf 會更加明晰且不容易產生引數順序問題的錯誤 —— 你可以在你的檢視函式定義中重新安排引數的順序。當然,這些好處是以簡潔為代價;有些開發人員認為命名組語法醜陋而繁瑣。

1.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的POSTGETHEAD等等 —— 都將路由到相同的函式。

1.4 捕獲的引數永遠是字串

每個捕獲的引數都作為一個普通的Python 字串傳遞給檢視,無論正則表示式使用的是什麼匹配方式。例如,下面這行URLconf 中:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

views.year_archive() 的year 引數將是一個字串

1.5 指定檢視引數的預設值

有一個方便的小技巧是指定檢視引數的預設值。 下面是一個URLconf 和檢視的示例:

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# View (in blog/views.py)
def page(request, num="1"):

    ...

在上面的例子中,兩個URL模式指向同一個檢視views.page —— 但是第一個模式不會從URL 中捕獲任何值。如果第一個模式匹配,page() 函式將使用num引數的預設值"1"。如果第二個模式匹配,page() 將使用正則表示式捕獲的num 值。

1.6 Including other URLconfs

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),
]

2、傳遞額外的選項給檢視函式

URLconfs 具有一個鉤子,讓你傳遞一個Python 字典作為額外的引數傳遞給檢視函式。

django.conf.urls.url() 函式可以接收一個可選的第三個引數,它是一個字典,表示想要傳遞給檢視函式的額外關鍵字引數。

例如:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

在這個例子中,對於/blog/2005/請求,Django 將呼叫views.year_archive(request, year='2005', foo='bar')

這個技術在Syndication 框架中使用,來傳遞元資料和選項給檢視。

3、name引數

'''

urlpatterns = [
    url(r'^index',views.index,name='INDEX'),

]
###################

def index(req):
    if req.method=='POST':
        username=req.POST.get('username')
        password=req.POST.get('password')
        if username=='alex' and password=='123':
            return HttpResponse("登陸成功")

    return render(req,'index.html')

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#     <form action="/index/" method="post">#}
     <form action="{% url 'INDEX' %}" method="post">
         使用者名稱:<input type="text" name="username">
         密碼:<input type="password" name="password">
         <input type="submit" value="submit">
     </form>
</body>
</html>


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

'''
View Code

 

二、編寫檢視

一個檢視函式,或者簡短來說叫做檢視,是一個簡單的Python函式,它接受web請求,並且返回web響應。響應可以是一張網頁的HTML內容,一個重定向,一個404錯誤,一個XML文件,或者一張圖片. . . 是任何東西都可以。無論檢視本身包含什麼邏輯,都要返回響應。程式碼寫在哪裡也無所謂,只要它在你的Python目錄下面。除此之外沒有更多的要求了——可以說“沒有什麼神奇的地方”。為了能夠把程式碼放在某個地方,慣例是把檢視放在叫做views.py的檔案中,然後把它放到你的專案或者應用目錄裡。

 

1、一個簡單的檢視

下面是一個返回當前日期和時間作為HTML文件的檢視:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

讓我們逐行閱讀上面的程式碼:

  • 首先,我們從 django.http模組匯入了HttpResponse類,以及Python的datetime庫。
  • 接著,我們定義了current_datetime函式。它是一個檢視函式。每個檢視函式都應接收HttpRequest物件作為第一個引數,一般叫做request。
  • 注意檢視函式的名稱並不重要;不需要用一個統一的命名方式來命名,以便讓Django識別它。我們將其命名為current_datetime,是因為這個名稱能夠精確地反映出它的功能。
  • 這個檢視會返回一個HttpResponse物件,其中包含生成的響應。每個檢視函式都要返回HttpResponse物件

'''
http請求-響應過程中有兩個核心物件:

http請求物件:HttpRequest

http響應響應:HttpResponse

所在位置:django.http

'''

2、快捷函式

2.1 render函式

---------------render(request, template_name[, context])

結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 物件。

引數:
     request: 用於生成響應的請求物件。

     template_name:要使用的模板的完整名稱,可選的引數

     context:新增到模板上下文的一個字典。預設是一個空字典。如果字典中的某個值是可呼叫的,檢視將在渲染模板之前呼叫它。

     content_type:生成的文件要使用的MIME型別。預設為DEFAULT_CONTENT_TYPE 設定的值。

     status:響應的狀態碼。預設為200。

2.2 redirect函式

-----------------------------------url.py

 url(r"login",   views.login),
 url(r"yuan_back",   views.yuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/yuan_back/")
            name="yuanhao"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def yuan_back(req):

    name="苑昊"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性別<input type="text" name="sex"></p>
    <p>郵箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>
-----------------------------------my backend.html
<h1>使用者{{ name }}你好</h1>

#總結: render和redirect的區別:
#   1 if render的頁面需要模板語言渲染,需要的將資料庫的資料載入到html,那麼所有的這一部分
#     除了寫在yuan_back的檢視函式中,必須還要寫在login中,程式碼重複,沒有解耦.

#   2 the most important: url沒有跳轉到/yuan_back/,而是還在/login/,所以當重新整理後
#     又得重新登入.