【Django】はじめてのDjangoアプリ第6回

django

PythonのWEBフレームワークDjangoを利用したアプリケーションの公式テュートリアルに沿ったWEBアプリケーション作成のメモ第6回です。

Writing your first Django app, part 3 | Django documentation
The web framework for perfectionists with deadlines.

前回は、Django Admin導入をしました。

今回はビューの追加をしていきます。

概要

ビューは、Django アプリケーション内の Web ページの「タイプ」であり、通常は特定の機能を提供し、特定のテンプレートを持ちます。

投票アプリケーションには、次の 4 つのビューがあります。

🟢質問の「インデックス」ページ – 最新のいくつかの質問が表示されます。
🟢質問の「詳細」ページ – 質問テキストが表示されます。結果はありませんが、投票フォームが表示されます。
🟢質問の「結果」ページ – 特定の質問の結果が表示されます。
🟢投票アクション – 特定の質問の特定の選択肢に対する投票を処理します。

Django では、Web ページやその他のコンテンツはビューによって配信されます。各ビューは Python 関数 (クラスベースのビューの場合はメソッド) によって表されます。 Django は、リクエストされた URL (正確には、URL のドメイン名の後の部分) を調べてビューを選択します。

Web を使用している今、ME2/Sites/dirmod.htm?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B のような美しいものに出会ったことがあるかもしれません。 Django では、それよりもはるかに洗練された URL パターンが使用できることを知っていただければ幸いです。

URL パターンは URL の一般的な形式です (例: /newsarchive/<year>/<month>/)。

URL からビューにアクセスするために、Django は「URLconfs」として知られるものを使用します。 URLconf は、URL パターンをビューにマップします。

このチュートリアルでは、URLconf の使用に関する基本的な手順を説明します。詳細については、URL ディスパッチャーを参照してください。

ビューの追加(ダミー)

次に、polls/views.py にさらにいくつかのビューを追加しましょう。これらのビューは引数を取るため、少し異なります。

▼「polls/views.py」

※追記するコード

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)

※完成形

from django.shortcuts import render
from django.http import HttpResponse

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)

次の path() 呼び出しを追加して、これらの新しいビューを polls.urls モジュールに接続します。

▼「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/34/」を見てください。これは、detail() 関数を実行し、URL で指定した ID を表示します。 「/polls/34/results/」と「/polls/34/vote/」も試してみてください。これらには、プレースホルダーの結果と投票ページが表示されます。

誰かがあなたの Web サイトからページ (たとえば、「/polls/34/」) をリクエストすると、Django は mysite.urls Python モジュールをロードします。これは、ROOT_URLCONF 設定によってポイントされているためです。これは、urlpatterns という名前の変数を見つけて、パターンを順番に走査します。 「polls/」で一致が見つかった後、一致するテキスト (「polls/」) が削除され、残りのテキスト (「34/」) がさらなる処理のために「polls.urls」 URLconf に送信されます。そこでは「 <int:question_id>/ 」と一致し、その結果、次のようにdetail()ビューが呼び出されます。

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

question_id=34 の部分は int:question_id から取得されます。山括弧を使用すると、URL の一部が「キャプチャ」され、それがキーワード引数として view 関数に送信されます。文字列の question_id 部分は、一致したパターンを識別するために使用される名前を定義し、int 部分は、どのパターンが URL パスのこの部分と一致するかを決定するコンバーターです。コンバーターとパターン名はコロン (:) で区切られます。

http://localhost:8000/polls/34/

http://localhost:8000/polls/34/results/

http://localhost:8000/polls/34/vote/

ビューの編集(実処理)

各ビューは、要求されたページのコンテンツを含む HttpResponse オブジェクトを返すこと、または Http404 などの例外を発生させることの 2 つのうちの 1 つを実行する責任があります。後は君しだい。

ビューはデータベースからレコードを読み取ることができるかどうかに関係なく、 Django のようなテンプレート システムやサードパーティの Python テンプレート システムを使用することも、使用しないこともできます。 PDF ファイルの生成、XML の出力、その場での ZIP ファイルの作成など、必要なものを何でも、必要な Python ライブラリを使用して実行できます。

Django が必要とするのは HttpResponse だけです。あるいは例外。

便利なので、チュートリアル 2 で説明した Django 独自のデータベース API を使用してみましょう。 ここでは、新しい Index() ビューを 1 つ試してみます。これは、システム内の最新の 5 つのアンケートの質問を、公開日に従ってカンマで区切って表示します。

▼「polls/views.py」

※冒頭に追記

from .models import Question

※「index()」を編集

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)

※完成形

from django.shortcuts import render
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)

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)

http://localhost:8000/polls/

ただし、ここには問題があります。ページのデザインはビュー内でハードコーディングされています。ページの外観を変更したい場合は、この Python コードを編集する必要があります。そこで、Django のテンプレート システムを使用して、ビューで使用できるテンプレートを作成することで、デザインを Python から分離しましょう。

まず、polls ディレクトリに templates というディレクトリを作成します。 Django はそこでテンプレートを探します。

プロジェクトの TEMPLATES 設定は、Django がテンプレートをどのようにロードしてレンダリングするかを記述します。デフォルト設定ファイルは、APP_DIRS オプションが True に設定されている DjangoTemplates バックエンドを構成します。慣例により、DjangoTemplates は各 INSTALLED_APPS で「templates」サブディレクトリを探します。

作成したばかりのテンプレート ディレクトリ内に、polls という名前の別のディレクトリを作成し、その中にindex.html というファイルを作成します。つまり、テンプレートは、polls/templates/polls/index.html にある必要があります。 app_directories テンプレート ローダーが上記で説明したように動作するため、Django 内でこのテンプレートを polls/index.html として参照できます。

テンプレートの名前空間

ここで、(別の polls サブディレクトリを作成するのではなく) テンプレートを polls/templates に直接配置することで回避できるかもしれませんが、実際には悪い考えです。 Django は、名前が一致する最初に見つかったテンプレートを選択します。別のアプリケーションに同じ名前のテンプレートがある場合、Django はそれらを区別できません。 Django に正しいものを指定できる必要があります。これを確実に行う最善の方法は、名前空間を設定することです。つまり、アプリケーション自体にちなんで名付けられた別のディレクトリ内にこれらのテンプレートを配置します。

そのテンプレートに次のコードを追加します。

▼「polls/templates/polls/index.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 %}

注記

チュートリアルを短くするために、すべてのテンプレートの例では不完全な HTML を使用しています。独自のプロジェクトでは、完全な HTML ドキュメントを使用する必要があります。

次に、テンプレートを使用するために、polls/views.py のインデックス ビューを更新しましょう。

▼「polls/views.py」

※冒頭に追記

from django.template import loader

※「index()」を編集

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))

※完成形

from django.shortcuts import render
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))

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)

このコードは、polls/index.html というテンプレートをロードし、コンテキストを渡します。コンテキストは、テンプレート変数名を Python オブジェクトにマッピングする辞書です。

ブラウザで「/polls/」をポイントしてページをロードすると、チュートリアル 2 の「What’s up」の質問を含む箇条書きリストが表示されます。リンクは質問の詳細ページを指します。

http://localhost:8000/polls/

※「What’s up?」のリンクをクリック

※次のような画面が表示される場合

「polls/templates/polls/index.html」の存在を確認したら、

開発用サーバーの再起動が必要です。

開発用サーバーのターミナルで[Ctrl]+Cを押し、

開発用サーバーを強制終了してから

python manage.py runserver

で再起動しましょう。

今回は以上です。次回はこの続きの予定です。

  • 0
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました