django檢視函式及快捷方式
檢視函式,簡稱檢視,本質上是一個簡單的Python函式,它接受Web請求並且返回Web響應。
響應的內容可以是HTML網頁、重定向、404錯誤,XML文件或影象等任何東西。但是,無論檢視本身是個什麼處理邏輯,最好都返回某種響應。
檢視函式的程式碼寫在哪裡也無所謂,只要它在你的Python目錄下面。但是通常我們約定將檢視放置在專案或應用程式目錄中的名為views.py的檔案中。
一、簡單的檢視
下面是一個返回當前日期和時間作為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,你可以取別的名字,但這不符合潛規則,最好不要那麼做。
- 檢視函式的名稱沒有強制規則,但儘量不要和Python及Django內建的各種名稱重名,並且儘量精確地反映出它的功能,比如這裡的
current_datetime
。 - 該檢視返回一個HttpResponse物件,其中包含生成的HTML頁面。
二、返回錯誤
在Django中返回HTTP錯誤程式碼是非常簡單的。
HttpResponse的許多子類對應著除了200(代表“OK”)以外的一些常用的HTTP狀態碼。
為了標示一個錯誤,可以直接返回那些子類中的一個例項,而不是普通的HttpResponse。像下面這樣:
from django.http import HttpResponse, HttpResponseNotFound def my_view(request): # ... if foo: return HttpResponseNotFound('<h1>Page not found</h1>') else: return HttpResponse('<h1>Page was found</h1>')
Django為404錯誤提供了一個特化的子類HttpResponseNotFound。由於一些狀態碼不太常用,所以不是每個狀態碼都有一個特化的子類。
也可以向HttpResponse的構造器傳遞HTTP狀態碼,來建立你想要的任何狀態碼的返回類。 像下面這樣:
from django.http import HttpResponse
def my_view(request): # ... # Return a "created" (201) response code. return HttpResponse(status=201)
關鍵是在返回中提供status=201
引數。別的什麼303之類的錯誤都可以參照上面的例子。
三、Http404異常
class django.http.Http404
這是一個Django內建的異常類。可以在需要的地方認為彈出它,Django會捕獲它,並且帶上HTTP404錯誤碼返回你當前app的標準錯誤頁面或者自定義錯誤頁面。像下面這樣:
from django.http import Http404
from django.shortcuts import render from polls.models import Poll def detail(request, poll_id): try: p = Poll.objects.get(pk=poll_id) except Poll.DoesNotExist: raise Http404("Poll does not exist") return render(request, 'polls/detail.html', {'poll': p})
為了在Django返回404時顯示自定義的HTML,可以建立一個名為404.html的HTML模板,並將其放置在模板樹的頂層。 當DEBUG設定為False時,此模板將被自動使用。當DEBUG為True時,可以向Http404提供訊息,它將顯示在標準的內建404除錯模板中,可以使用這些訊息進行除錯。
三、Django內建的快捷方法
Django在django.shortcuts
模組中,為我們提供了很多快捷方便的類和方法,它們都很重要,使用頻率很高。
1. render()
render(request, template_name, context=None, content_type=None, status=None, using=None)[source]
結合一個給定的模板和一個給定的上下文字典,返回一個渲染後的HttpResponse物件。
必需引數:
- request:檢視函式處理的當前請求,封裝了請求頭的所有資料,其實就是檢視引數request。
- template_name:要使用的模板的完整名稱或者模板名稱的列表。如果是一個列表,將使用其中能夠查詢到的第一個模板。
可選引數:
- context:新增到模板上下文的一個數據字典。預設是一個空字典。可以將認可需要提供給模板的資料以字典的格式新增進去。這裡有個小技巧,使用Python內建的locals()方法,可以方便的將函式作用於內的所有變數一次性新增。
- content_type:用於生成的文件的MIME型別。 預設為
DEFAULT_CONTENT_TYPE
設定的值。 - status:響應的狀態程式碼。 預設為200。
- using:用於載入模板使用的模板引擎的NAME。
範例:
下面的例子將渲染模板myapp/index.html
,MIME型別為application/xhtml+xml
:
from django.shortcuts import render
def my_view(request): # View code here... return render(request, 'myapp/index.html', { 'foo': 'bar', }, content_type='application/xhtml+xml')
這個示例等同於:
from django.http import HttpResponse
from django.template import loader def my_view(request): # View code here... t = loader.get_template('myapp/index.html') c = {'foo': 'bar'} return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
2. render_to_response()
render_to_response(template_name, context=None, content_type=None, status=None, using=None)[source]
此功能在引入render()之前進行,不推薦,以後可能會被棄用。
3. redirect()
redirect(to, permanent=False, args, *kwargs)[source]
根據傳遞進來的url引數,返回HttpResponseRedirect。
引數to可以是:
- 一個模型:將呼叫模型的
get_absolute_url()
函式,反向解析出目的url; - 檢視名稱:可能帶有引數:reverse()將用於反向解析url;
- 一個絕對的或相對的URL:將原封不動的作為重定向的目標位置。
預設情況下是臨時重定向,如果設定permanent=True
將永久重定向。
範例:
1.呼叫物件的get_absolute_url()
方法來重定向URL:
from django.shortcuts import redirect
def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)
2.傳遞檢視名,使用reverse()方法反向解析url:
def my_view(request):
... return redirect('some-view-name', foo='bar')
- 重定向到硬編碼的URL:
def my_view(request):
... return redirect('/some/url/')
- 重定向到一個完整的URL:
def my_view(request):
... return redirect('https://example.com/')
所有上述形式都接受permanent引數;如果設定為True,將返回永久重定向:
def my_view(request):
... object = MyModel.objects.get(...) return redirect(object, permanent=True)
4. get_object_or_404()
get_object_or_404(klass, args, *kwargs)[source]
這個方法,非常有用,請一定熟記。常用於查詢某個物件,找到了則進行下一步處理,如果未找到則給使用者返回404頁面。
在後臺,Django其實是呼叫了模型管理器的get()方法,只會返回一個物件。不同的是,如果get()發生異常,會引發Http404異常,從而返回404頁面,而不是模型的DoesNotExist異常。
必需引數:
- klass:要獲取的物件的Model類名或者Queryset等;
**kwargs
:查詢的引數,格式應該可以被get()接受。
範例:
1.從MyModel中使用主鍵1來獲取物件:
from django.shortcuts import get_object_or_404
def my_view(request): my_object = get_object_or_404(MyModel, pk=1)
這個示例等同於:
from django.http import Http404
def my_view(request): try: my_object = MyModel.objects.get(pk=1) except MyModel.DoesNotExist: raise Http404("No MyModel matches the given query.")
2.除了傳遞Model名稱,還可以傳遞一個QuerySet例項:
queryset = Book.objects.filter(title__startswith='M') get_object_or_404(queryset, pk=1)
上面的示例不夠簡潔,因為它等同於:
get_object_or_404(Book, title__startswith='M', pk=1)
但是如果你的queryset來自其它地方,它就會很有用了。
3.還可以使用Manager。 如果你自定義了管理器,這將很有用:
get_object_or_404(Book.dahl_objects, title='Matilda')
4.還可以使用related managers:
author = Author.objects.get(name='Roald Dahl') get_object_or_404(author.book_set, title='Matilda')
與get()一樣,如果找到多個物件將引發一個MultipleObjectsReturned異常。
5. get_list_or_404()
get_list_or_404(klass, args, *kwargs)[source]
這其實就是get_object_or_404
多值獲取版本。
在後臺,返回一個給定模型管理器上filter()的結果,並將結果對映為一個列表,如果結果為空則彈出Http404異常。
必需引數:
- klass:獲取該列表的一個Model、Manager或QuerySet例項。
**kwargs
:查詢的引數,格式應該可以被filter()接受。
範例:
下面的示例從MyModel中獲取所有釋出出來的物件:
from django.shortcuts import get_list_or_404
def my_view(request): my_objects = get_list_or_404(MyModel, published=True)
這個示例等同於:
from django.http import Http404
def my_view(request): my_objects = list(MyModel.objects.filter(published=True)) if not my_objects: raise Http404("No MyModel matches the given query.")