python(django(管路頁面、概況、編寫檢視佔位、編寫一個真正的檢視、丟擲錯誤、檢視使用模板系統、去除硬編碼url、為url新增命名開空間、編寫表單))

yytkkn發表於2021-01-03

學習目標:

Python學習十八-Django、


學習內容:

1、介紹 Django 管理頁面
2、django概況
3、django編寫檢視
4、django編寫一個真正的檢視
5、django丟擲404錯誤
6、django檢視使用模板系統
7、django去除模板中的硬編碼 URL
8、django為 URL 名稱新增名稱空間
9、django編寫一個表單


1、介紹 Django 管理頁面

1、建立一個管理員賬號
在pycharm中的terminal輸入下列指令:

python manage.py createsuperuser

(base) F:\pycharm\project\Django\yyt>python manage.py createsuperuser
Username (leave blank to use 'administrator'): root
Email address: 812277079@qq.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

2、啟動開發伺服器

python manage.py runserver

  • 開啟瀏覽器,轉到你本地域名的 “/admin/” 目錄, – 比如 “http://127.0.0.1:8000/admin/”
    在這裡插入圖片描述
    3、進入管理站點頁面
    利用剛才建立的使用者和密碼登入

可編輯的內容:組和使用者,它們是由 django.contrib.auth 提供的,這是 Django 開發的認證框架
在這裡插入圖片描述

4、向管理頁面中加入應用
前面我們建立了投票應用,把投票應用加入到管理頁面

  • 告訴管理頁面,問題 Question 物件需要被管理,開啟 polls/admin.py 檔案,編輯如下:
from django.contrib import admin
from .models import Question

admin.site.register(Question)

5、體驗便捷的管理功能
管理頁面註冊了問題 Question 類,在頁面中可以很方便的對該類進行操作了
在這裡插入圖片描述


2、django概況

  • Django 中的檢視:一類具有相同功能和模板的網頁的集合
  • 在 Django 中,網頁和其他內容都是從檢視派生而來。每一個檢視表現為一個簡單的 Python
    函式(或者說方法,如果是在基於類的檢視裡的話),Django 將會根據使用者請求的 URL 來選擇使用哪個檢視(更準確的說,是根據 URL中域名之後的部分)
  • URL 模式中 URL 的基本格式,舉個例子:/newsarchive///
  • Django 使用了 ‘URLconfs’ 來配置將 URL 和檢視關聯起來,URLconf 將 URL 模式對映到檢視

3、django編寫檢視

根據之前建立的yyt專案(polls應用),進行一下一些編寫
1、建立新的檢視並且新增到polls.urls裡面

  • 向 yyt專案的polls/views.py 裡新增更多檢視,這些檢視有一些不同,因為他們接收引數
def detail(request,question_id):
    return HttpResponse('you are looking at question %s.'% question_id)


def results(request,question_id):
    response = 'you are looking at the results of question %s'
    return HttpResponse(response,question_id)


def vote(request,question_id):
    return HttpResponse('you`re voting on question %s' % question_id)
  • 把這些新檢視新增進 polls.urls 模組裡,只要新增幾個 url() 函式呼叫
 urlpatterns = [
    path('',views.index, name='index'),
    path('<int:question_id>/',views.detail,name = 'detail'),
    path('<int:question_id>/results/',views.results,name = 'results'),
    path('<int:question_id>/vote/',views.vote,name = 'vate'),
]
  • 然後在瀏覽器,輸入 “http://127.0.0.1:8000/polls/34/” ,Django 將會執行 detail()方法並且展示你在 URL 裡提供的問題 ID,再試試 “/polls/34/vote/” 和 “/polls/34/vote/”,你將會看到暫時用於佔位的結果和投票頁
    在這裡插入圖片描述
  • 當請求網站的某一頁面時,比如 “http://127.0.0.1:8000/polls/34/”,Django會載入yyt.urls模組,因為這在配置項 ROOT_URLCONF 中設定了,然後 Django 尋找名為urlpatterns 變數並且按序匹配正規表示式,在找到匹配項’polls/’,它切掉了匹配的文字(“polls/”),將剩餘文字"34/",傳送至 ‘polls.urls’ URLconf做進一步處理,在這裡剩餘文字匹配了 ‘<int:question_id>/’,使得我們 Django 以如下形式呼叫 detail():

question_id=34 由 <int:question_id> 匹配生成,尖括號“捕獲”這部分URL,以關鍵字引數的形式傳送給檢視函式,’<int:question_id>/的 :question_id>部分定義了將被用於區分匹配模式的變數名,int: 則是一個轉換器決定了應該以什麼變數型別匹配這部分的 URL 路徑

detail(request=<HttpRequest object>, question_id=34)

4、django編寫一個真正的檢視

  • 檢視必須要做的只有兩件事:返回一個包含被請求頁面內容的 HttpResponse 物件,或者丟擲一個異常,比如 Http404,至於你還想幹些什麼,隨便你
  • Django 只要求返回的是一個 HttpResponse ,或者丟擲一個異常

1、呼叫django的API介面,在index裡面加入內容,展示資料庫裡以釋出日期排序的最近 5 個投票問題,以空格分割:

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

2、使用 Django 的模板系統建立一個檢視,將頁面的設計從程式碼中分離出來改變頁面的樣子

  • 在專案yyt中建立一個 templates 目錄,Django 將會在這個目錄裡查詢模板檔案

專案的TEMPLATES配置項描述了Django如何載入和渲染模板,預設的設定檔案設定了DjangoTemplates 後端,並將APP_DIRS設定成了 True,這將會讓DjangoTemplates在每個INSTALLED_APPS資料夾中尋找 “templates” 子目錄,這就是為什麼儘管我們沒有像在第二部分中那樣修改 DIRS 設定,Django 也能正確找到polls 的模板位置的原因

在建立的 templates 目錄裡,新建一個檔案 index.html,模板檔案的路徑應該是yyt/templates/index.html ,Django會找到對應的app_directories,你只需要使用polls/index.html 就可以引用到這一模板

在這裡插入圖片描述

  • 在polls應用檢視中利用快捷函式重新編寫index程式碼訪問資料庫,並且返回值到indx.html

快捷函式:render()

def index(request):
    q_all = Question.objects.all()
    context = {'q_all': q_all}
    return render(request, 'index.html', context)
  • 編寫indx.html,遍歷views檢視返回的資料庫
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if q_all %}
<ul>
{% for i in q_all %}
    <li><a href="/polls/{{i.id}}/">{{i.question_text}}</a></li>
{% endfor %}
</ul>
{%else%}
<p>No polls are available.</p>
{%endif%}
</body>
</html>

在這裡插入圖片描述
點選第三個超連結:
在這裡插入圖片描述


5、django丟擲404錯誤

1、嘗試用 get() 函式獲取一個物件,如果不存在就丟擲 Http404 錯誤也是一個普遍的流程

  • 在views檢視中編寫detail方法
from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})
  • 在templates中新建一個detail.html檔案,輸入如下:
{{ question }}
  • 隨便輸入一個question_id,顯示如下:
    在這裡插入圖片描述
    2、一個快捷函式: get_object_or_404()
    django提供一個快捷函式丟擲404錯誤

get_object_or_404()

from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

6、django檢視使用模板系統

detail檢視返回的值到detail.html模板

  • 編寫detail.html模板

for函式會遍歷question.choice_set.all返回可迭代物件choice,choice可以在物件所在標籤內使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
</body>
</html>
  • 當在polls應用中點選index檢視返回到index.html模板的question_text時,會跳轉到detail檢視返回的detail.html模板

點選第一個question_id為1:
在這裡插入圖片描述
直接輸入一個不存在的question_id時會返回404:
在這裡插入圖片描述


7、django去除模板中的硬編碼 URL

polls/index.html 裡編寫投票連結時,連結是硬編碼的
1、因為在 polls.urls 的 url() 函式中通過 name 引數為 URL 定義了名字,可以使用 {% url %} 標籤

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
替換成
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

2、如果想改變投票詳情檢視的 URL

  • 比如想改成 polls/specifics/12/ ,只需要在 polls/urls.py 裡修改
path('specifics/<int:question_id>/', views.detail, name='detail'),

8、django為 URL 名稱新增名稱空間

django在根 URLconf 中新增名稱空間,在 polls/urls.py 檔案中加上 app_name 設定名稱空間,就可以分辨重名的 URL

  • 舉個例子:polls 應用有 detail 檢視,可能另一個部落格應用也有同名的檢視,Django 可以知道 {% url %}標籤對應應用的 URL
from django.urls import path

from .views import *
app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
  • 可根據修改的polls/urls.py修改index.html
<li><a href="{% url 'polls:detail' i.id %}">{{ i.question_text }}</a></li>

9、django編寫一個表單

改寫templates中detail.html程式碼,實現一個簡單的表單
1、利用html的相關標籤實現表單

  • 每個單選按鈕的 value 屬性是對應的各個 Choice 的 ID
  • name 是 “choice”,選擇單選按鈕並提交表單提交時,傳送一個 POST 資料choice=choice_id
  • forloop.counter 指示 for標籤已經迴圈多少次
  • django針對內部 URL 的 POST 表單都應該使用 {% csrf_token %} 模板標籤
  • 改寫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>

或者

<!DOCTYPE html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--<h1>{{ question.question_text }}</h1>-->
<!--<ul>-->
<!--{% for choice in question.choice_set.all %}-->
<!--    <li>{{ choice.choice_text }}</li><input type="radio" name="choice">-->
<!--{% endfor %}-->
<!--</ul>-->
<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 %}
    {% if choice.choice_text == '是' %}
    <input type="radio" name="choice" id="choice{{ forloop.counter}}" value="{{ choice.id }}" checked>
    {% else %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >

    {% endif %}
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
    <input type="submit" value="Vote">
</form>
</body>
  • 改寫vote檢視,處理提交的資料,之前已經建立了vote檢視的URLconf
  • request.POST 是一個類字典物件,讓你可以通過關鍵字的名字獲取提交的資料
  • reverse()呼叫將返回一個url地址:’/polls/3/results/’
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse,HttpResponseRedirect
from django.urls import reverse
from .models import Question, Choice


def results(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()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
  • 編寫result檢視,對 Question 進行投票後, vote() 檢視將請求重定向到 Question 的結果介面
def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

相關文章