[Django] tutorial #3-view

26995 ワード

ビューの追加

polls/views.pyを開いてビューを追加し、次のコードを記述します.
- polls/views.py
def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
    
def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're 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)
ここで覚えておきたいのは
ビューは、クライアントからrequestを受信し、responseを返します.
このときrequestには多くの情報が含まれている.response以前は、ビューは、データを抽出してもよいし、データを記憶してもよいし、Webに対して種々の処理を行うことができる.polls/urls.pyを開き、追加したビューを呼び出すためにURLコードを記述します.
- polls/urls.py
from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
/polls/呼び出しアドレスindexビュー.
呼び出されたindexビューには、「Hello,world.You're at the policies index」が表示されます.resposeをクライアントに返します.
次は、将来サポートされるurlモードです.
- <int:question_id>/- <int:question_id>/results/- <int:question_id>/vote/ここで注意すべき点は
urlコードに示されるquestion_idは、ビューのquestion_idと一致する必要があります.

viewに実際にいくつかの操作を実行させる


これまでindexビューを呼び出した場合
"Hello, world. You're at the polls index."というstrを返すと、
これで、システムに格納されている少なくとも5つの投票問題がカンマで区切られ、発行日に基づいて出力されます.
- polls/views.py
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)

# Leave the rest of the views (detail, results, vote) unchanged
次に、indexビューが呼び出されると、requestがクライアントから受信される.Questionデータの発行日(pub-date)5개にソートし、カンマ(,)に接続してstrを返します.

分離テンプレート


これまで、ビューにクライアントへのページが表示されていました.これは、データを抽出してすぐにクライアントに返す方法です.
しかし、このようにして、設計を変更する際にクライアントに表示されるページの変更は非常に複雑になる.
設計を変更するには、ビューの内部を変更する必要があるからです.
そのため、内部ロジックを担当するビューと設計を担当するテンプレートを分離する必要があります.
まず、pollsディレクトリにtemplatesというディレクトリを作成します.
この場合、ディレクトリにディレクトリを作成し、アプリケーション名templates管理ファイル(polls)を使用する必要があります.
これは、アプリケーション名の別のディレクトリを作成しないと、長いライブラリが他のアプリケーションのテンプレートと区別できないためです.
polls/
    migrations/
    templates/polls
    	index.html
テンプレートに次のコードを記述します.
- html
{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}
作成したテンプレートを使用して、polls/templates/polls/index.htmlpolls/views.pyビューを更新
- index
from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))
コードの表示:polls/views.pyteplateは、loadを返します.
テンプレートのデータは、resposeで転送できます.contextはテンプレートにデータを渡し、テンプレートはこれらのデータを使用します.
テンプレートは、ビューからデータlatest_question_listを受信し、クライアントに表示するリストを作成します.

(last question list)コード量を減らす

render()関数を使用すると、コード量を減らすことができます.
構造化タスクのソースコードを低減するために、本明細書では、単純な関数表現のショートカットrenderを提供する.
- (shortcuts)
from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

404異常発生


プログラミング時にエラーをどのように処理するかは重要な面です.polls/views.pyビューでエラーが発生しました.
- 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})
- polls/views.py
{{ question }}
コードを作成した後、クエリーにないデータを検索するとエラーが発生し、例外メッセージ「Question not exist」を返します.

polls/templates/polls/detail.html


データが存在しない場合、get_object_or_404()Http 404異常がよく使用される.この機能のショートカットget()を提供します.
先ほど作成した(shortcuts)ビューのショートカットを使用して、次の変更を行います.
- detail
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})

テンプレートシステムの使用

polls/views.pyビューもdetail変数contextです.
下記のように修正します.
- question
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
このときコードを説明すると、以下のようになります.
  • polls/detail.html:テンプレートはスキップされますpolls/templates/polls/detail.html,<h1>{{ question.question_text }}</h1>データのquestionタイトルは
  • question:外部キーquestion_textとして受信した{% for choice in question.choice_set.all %}をすべての
  • にインポート
  • question:インポートした(ForeignKey)をリストに入れる
    ひとつひとつ入れる
  • コードを変更してサーバーを表示すると、choiceがタイトルになります.
    以下の<li>{{ choice.choice_text }}</li>のすべてのリストが表示されます.

    テンプレートからハードコーディングの選択を削除


    現在、question_textファイルのchoice部分はハードコーディングされています.
    - url
    <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    この場合、index.htmlが変更された場合、テンプレートのurlも変更する必要があります.
    この点を改善するために.
    典故では、polls/templates/polls/index.htmlurl毎にurlを明記することができる.urlコードにnameを宣言し、テンプレートにurlを直接書き込みます.
    修正後のnameは一意の名前を持つため、テンプレート内のソースコードを変更する必要はありません.
    したがって、ハードコーディングのnameを削除するには、次のコードを変更します.
    - url
    <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
    この場合、このurlの一意の名前はpolls/templates/polls/index.htmlファイルで見つけることができる.
    - url
    ...
    # the 'name' value as called by the {% url %} template tag
    path('<int:question_id>/', views.detail, name='detail'),
    ...

    polls/ulrs.pyのネーミングスペースの指定


    これまで、polls/ulrs.pyというアプリケーションは1つしかありませんでした.
    実際のプロジェクトをすると、いくつかのアプリケーションがあるかもしれません.urlアプリケーションにはpollsのビューがあり、例えば別のpollsアプリケーションにもdetailのビューがあり得る.
    さっき上で作ったように.
    テンプレート内のblogタグがdetailに設定されている場合、どのアプリケーションビューで生成されたurlを区別することはできません.
    したがって、各アプリケーションの{% url %}をマーケティングマネージャに区別させることができます.
    アプリケーションで使用されるurlには、アプリケーション名を明記します.
    - url
    from django.urls import path
    
    from . import views
    
    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'),
    ]
    名前が明確になったら、テンプレートに追加します.
    - url
    <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    🔎 リファレンス
    デジタルカメラ公式ファイル
    デジタルウェアハウス公式ドキュメント講義