欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
編寫(xiě)你的第一個(gè) Django 應用,第 4 部分 | Django 文檔 | Django

編寫(xiě)你的第一個(gè) Django 應用,第 4 部分?

這一篇從 教程第 3 部分 結尾的地方繼續講起。我們將繼續編寫(xiě)投票應用,專(zhuān)注于簡(jiǎn)單的表單處理并且精簡(jiǎn)我們的代碼。

編寫(xiě)一個(gè)簡(jiǎn)單的表單?

讓我們更新一下在上一個(gè)教程中編寫(xiě)的投票詳細頁(yè)面的模板 ("polls/detail.html") ,讓它包含一個(gè) HTML <form> 元素:

polls/templates/polls/detail.html?
<h1>{{ question.question_text }}</h1>{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}<form action="{% url 'polls:vote' question.id %}" method="post">{% csrf_token %}{% for choice in question.choice_set.all %}    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>{% endfor %}<input type="submit" value="Vote"></form>

簡(jiǎn)要說(shuō)明:

  • 上面的模板在 Question 的每個(gè) Choice 前添加一個(gè)單選按鈕。 每個(gè)單選按鈕的 value 屬性是對應的各個(gè) Choice 的 ID。每個(gè)單選按鈕的 name"choice" 。這意味著(zhù),當有人選擇一個(gè)單選按鈕并提交表單提交時(shí),它將發(fā)送一個(gè) POST 數據 choice=# ,其中# 為選擇的 Choice 的 ID。這是 HTML 表單的基本概念。

  • 我們設置表單的 action{% url 'polls:vote' question.id %} ,并設置 method="post" 。使用 method="post"``(與其相對的是 ``method="get"`)是非常重要的,因為這個(gè)提交表單的行為會(huì )改變服務(wù)器端的數據。 無(wú)論何時(shí),當你需要創(chuàng )建一個(gè)改變服務(wù)器端數據的表單時(shí),請使用 ``method="post" 。這不是 Django 的特定技巧;這是優(yōu)秀的網(wǎng)站開(kāi)發(fā)技巧。

  • forloop.counter 指示 for 標簽已經(jīng)循環(huán)多少次。

  • 由于我們創(chuàng )建一個(gè) POST 表單(它具有修改數據的作用),所以我們需要小心跨站點(diǎn)請求偽造。 謝天謝地,你不必太過(guò)擔心,因為 Django 已經(jīng)擁有一個(gè)用來(lái)防御它的非常容易使用的系統。 簡(jiǎn)而言之,所有針對內部 URL 的 POST 表單都應該使用 {% csrf_token %} 模板標簽。

現在,讓我們來(lái)創(chuàng )建一個(gè) Django 視圖來(lái)處理提交的數據。記住,在 教程第 3 部分 中,我們?yōu)橥镀睉脛?chuàng )建了一個(gè) URLconf ,包含這一行:

polls/urls.py?
path('<int:question_id>/vote/', views.vote, name='vote'),

我們還創(chuàng )建了一個(gè) vote() 函數的虛擬實(shí)現。讓我們來(lái)創(chuàng )建一個(gè)真實(shí)的版本。 將下面的代碼添加到 polls/views.py

polls/views.py?
from django.http import HttpResponse, HttpResponseRedirectfrom django.shortcuts import get_object_or_404, renderfrom django.urls import reversefrom .models import Choice, Question# ...def vote(request, question_id):    question = get_object_or_404(Question, pk=question_id)    try:        selected_choice = question.choice_set.get(pk=request.POST['choice'])    except (KeyError, Choice.DoesNotExist):        # Redisplay the question voting form.        return render(request, 'polls/detail.html', {            'question': question,            'error_message': "You didn't select a choice.",        })    else:        selected_choice.votes += 1        selected_choice.save()        # Always return an HttpResponseRedirect after successfully dealing        # with POST data. This prevents data from being posted twice if a        # user hits the Back button.        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

以上代碼中有些內容還未在本教程中提到過(guò):

  • request.POST 是一個(gè)類(lèi)字典對象,讓你可以通過(guò)關(guān)鍵字的名字獲取提交的數據。 這個(gè)例子中, request.POST['choice'] 以字符串形式返回選擇的 Choice 的 ID。 request.POST 的值永遠是字符串。

    注意,Django 還以同樣的方式提供 request.GET 用于訪(fǎng)問(wèn) GET 數據 —— 但我們在代碼中顯式地使用 request.POST ,以保證數據只能通過(guò) POST 調用改動(dòng)。

  • 如果在 request.POST['choice'] 數據中沒(méi)有提供 choice , POST 將引發(fā)一個(gè) KeyError 。上面的代碼檢查 KeyError ,如果沒(méi)有給出 choice 將重新顯示 Question 表單和一個(gè)錯誤信息。

  • 在增加 Choice 的得票數之后,代碼返回一個(gè) HttpResponseRedirect 而不是常用的 HttpResponse 、 HttpResponseRedirect 只接收一個(gè)參數:用戶(hù)將要被重定向的 URL(請繼續看下去,我們將會(huì )解釋如何構造這個(gè)例子中的 URL)。

    As the Python comment above points out, you should always return anHttpResponseRedirect after successfully dealing withPOST data. This tip isn't specific to Django; it's just good Webdevelopment practice.

  • 在這個(gè)例子中,我們在 HttpResponseRedirect 的構造函數中使用 reverse() 函數。這個(gè)函數避免了我們在視圖函數中硬編碼 URL。它需要我們給出我們想要跳轉的視圖的名字和該視圖所對應的 URL 模式中需要給該視圖提供的參數。 在本例中,使用在 教程第 3 部分 中設定的 URLconf, reverse() 調用將返回一個(gè)這樣的字符串:

    '/polls/3/results/'

    其中 3question.id 的值。重定向的 URL 將調用 'results' 視圖來(lái)顯示最終的頁(yè)面。

正如在 教程第 3 部分 中提到的,HttpRequest 是一個(gè) HttpRequest 對象。更多關(guān)于 HttpRequest 對象的內容,請參見(jiàn) 請求和響應的文檔 。

當有人對 Question 進(jìn)行投票后, vote() 視圖將請求重定向到 Question 的結果界面。讓我們來(lái)編寫(xiě)這個(gè)視圖:

polls/views.py?
from django.shortcuts import get_object_or_404, renderdef results(request, question_id):    question = get_object_or_404(Question, pk=question_id)    return render(request, 'polls/results.html', {'question': question})

這和 教程第 3 部分 中的 detail() 視圖幾乎一模一樣。唯一的不同是模板的名字。 我們將在稍后解決這個(gè)冗余問(wèn)題。

現在,創(chuàng )建一個(gè) polls/results.html 模板:

polls/templates/polls/results.html?
<h1>{{ question.question_text }}</h1><ul>{% for choice in question.choice_set.all %}    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>{% endfor %}</ul><a href="{% url 'polls:detail' question.id %}">Vote again?</a>

現在,在你的瀏覽器中訪(fǎng)問(wèn) /polls/1/ 然后為 Question 投票。你應該看到一個(gè)投票結果頁(yè)面,并且在你每次投票之后都會(huì )更新。 如果你提交時(shí)沒(méi)有選擇任何 Choice,你應該看到錯誤信息。

注解

我們的 vote() 視圖代碼有一個(gè)小問(wèn)題。代碼首先從數據庫中獲取了 selected_choice 對象,接著(zhù)計算 vote 的新值,最后把值存回數據庫。如果網(wǎng)站有兩個(gè)方可同時(shí)投票在 同一時(shí)間 ,可能會(huì )導致問(wèn)題。同樣的值,42,會(huì )被 votes 返回。然后,對于兩個(gè)用戶(hù),新值43計算完畢,并被保存,但是期望值是44。

這個(gè)問(wèn)題被稱(chēng)為 競爭條件 。如果你對此有興趣,你可以閱讀 Avoiding race conditions using F() 來(lái)學(xué)習如何解決這個(gè)問(wèn)題。

使用通用視圖:代碼還是少點(diǎn)好?

detail() (在 教程第3部分 中)和 results() 視圖都很簡(jiǎn)單 —— 并且,像上面提到的那樣,存在冗余問(wèn)題。用來(lái)顯示一個(gè)投票列表的 index() 視圖(也在 教程第 3 部分 中)和它們類(lèi)似。

這些視圖反映基本的 Web 開(kāi)發(fā)中的一個(gè)常見(jiàn)情況:根據 URL 中的參數從數據庫中獲取數據、載入模板文件然后返回渲染后的模板。 由于這種情況特別常見(jiàn),Django 提供一種快捷方式,叫做“通用視圖”系統。

通用視圖將常見(jiàn)的模式抽象化,可以使你在編寫(xiě)應用時(shí)甚至不需要編寫(xiě)Python代碼。

讓我們將我們的投票應用轉換成使用通用視圖系統,這樣我們可以刪除許多我們的代碼。我們僅僅需要做以下幾步來(lái)完成轉換,我們將:

  1. 轉換 URLconf。

  2. 刪除一些舊的、不再需要的視圖。

  3. 基于 Django 的通用視圖引入新的視圖。

請繼續閱讀來(lái)了解詳細信息。

為什么要重構代碼?

一般來(lái)說(shuō),當編寫(xiě)一個(gè) Django 應用時(shí),你應該先評估一下通用視圖是否可以解決你的問(wèn)題,你應該在一開(kāi)始使用它,而不是進(jìn)行到一半時(shí)重構代碼。本教程目前為止是有意將重點(diǎn)放在以“艱難的方式”編寫(xiě)視圖,這是為將重點(diǎn)放在核心概念上。

就像在使用計算器之前你需要掌握基礎數學(xué)一樣。

改良 URLconf?

首先,打開(kāi) polls/urls.py 這個(gè) URLconf 并將它修改成:

polls/urls.py?
from django.urls import pathfrom . import viewsapp_name = 'polls'urlpatterns = [    path('', views.IndexView.as_view(), name='index'),    path('<int:pk>/', views.DetailView.as_view(), name='detail'),    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),    path('<int:question_id>/vote/', views.vote, name='vote'),]

注意,第二個(gè)和第三個(gè)匹配準則中,路徑字符串中匹配模式的名稱(chēng)已經(jīng)由 <question_id> 改為 <pk>。

改良視圖?

下一步,我們將刪除舊的 index, detail, 和 results 視圖,并用 Django 的通用視圖代替。打開(kāi) polls/views.py 文件,并將它修改成:

polls/views.py?
from django.http import HttpResponseRedirectfrom django.shortcuts import get_object_or_404, renderfrom django.urls import reversefrom django.views import genericfrom .models import Choice, Questionclass IndexView(generic.ListView):    template_name = 'polls/index.html'    context_object_name = 'latest_question_list'    def get_queryset(self):        """Return the last five published questions."""        return Question.objects.order_by('-pub_date')[:5]class DetailView(generic.DetailView):    model = Question    template_name = 'polls/detail.html'class ResultsView(generic.DetailView):    model = Question    template_name = 'polls/results.html'def vote(request, question_id):    ... # same as above, no changes needed.

我們在這里使用兩個(gè)通用視圖: ListViewDetailView 。這兩個(gè)視圖分別抽象“顯示一個(gè)對象列表”和“顯示一個(gè)特定類(lèi)型對象的詳細信息頁(yè)面”這兩種概念。

  • 每個(gè)通用視圖需要知道它將作用于哪個(gè)模型。 這由 model 屬性提供。

  • DetailView 期望從 URL 中捕獲名為 "pk" 的主鍵值,所以我們?yōu)橥ㄓ靡晥D把 question_id 改成 pk 。

默認情況下,通用視圖 DetailView 使用一個(gè)叫做 <app name>/<model name>_detail.html 的模板。在我們的例子中,它將使用 "polls/question_detail.html" 模板。template_name 屬性是用來(lái)告訴 Django 使用一個(gè)指定的模板名字,而不是自動(dòng)生成的默認名字。 我們也為 results 列表視圖指定了 template_name —— 這確保 results 視圖和 detail 視圖在渲染時(shí)具有不同的外觀(guān),即使它們在后臺都是同一個(gè) DetailView 。

類(lèi)似地,ListView 使用一個(gè)叫做 <app name>/<model name>_list.html 的默認模板;我們使用 template_name 來(lái)告訴 ListView 使用我們創(chuàng )建的已經(jīng)存在的 "polls/index.html" 模板。

在之前的教程中,提供模板文件時(shí)都帶有一個(gè)包含 questionlatest_question_list 變量的 context。對于 DetailView , question 變量會(huì )自動(dòng)提供—— 因為我們使用 Django 的模型 (Question), Django 能夠為 context 變量決定一個(gè)合適的名字。然而對于 ListView, 自動(dòng)生成的 context 變量是 question_list。為了覆蓋這個(gè)行為,我們提供 context_object_name 屬性,表示我們想使用 latest_question_list。作為一種替換方案,你可以改變你的模板來(lái)匹配新的 context 變量 —— 這是一種更便捷的方法,告訴 Django 使用你想使用的變量名。

啟動(dòng)服務(wù)器,使用一下基于通用視圖的新投票應用。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Django 實(shí)戰3
Django學(xué)習與實(shí)戰(四):基于類(lèi)的通用視圖詳解
第124天: Web 開(kāi)發(fā) Django 模板
PyCharm 開(kāi)發(fā)Django ,錯誤匯總
前端教程:Django模板系統
Django(URL、Views、Template)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久