サイドバーの「Django ドキュメント検索」というプレースホルダの入った検索では、Django ドキュメント (Django 2.1) の公式サイト内を検索できます
Django チュートリアルの進め方 その 4 (2)

目次

はじめに

Django を学習するには、何はともあれ公式チュートリアル「はじめての Django アプリ作成」からスタートしてみるのが良いでしょう。しかし、いざチュートリアル通りに進めようとしても躓く場合も多いと思います。そこで、「チュートリアルの進め方」シリーズとして、チュートリアルに沿った作業を行いながら補足事項をまとめることにしました。チュートリアルで躓いた際のヒントとしてお使いください。

利用環境は Ubuntu、 Linux Mint を中心として説明しますが、 Windows についても補足します。

前回は、Django チュートリアルの進め方 その 4 (1) と題してはじめての Django アプリ作成、その 4の前半についてまとめました。

今回は、はじめての Django アプリ作成、その 4 の後半についてまとめました。

汎用ビューを使う: コードが少ないのはいいことだ

ここまでのチュートリアルで記述してきたビューの書き方は、基本形ではありますが、実践ではクラスベースのビュー (汎用ビュー) を使った記述を中心とし、それで対応できない場合にこれまでのような関数ベースのビューで記述することになります。ここからは、ビューをクラスベースに書き換えて行きます。

URLconf の修正

polls.urls.py を書き換えます。

from django.urls import path

from . import views

app_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'),
]


今までのビューのうち、index, detail, result をクラスベースの汎用ビューに置き換えます。それぞれ IndexView, DetailView, ResultsView というクラスを定義します。これらのクラスは as_view() を使って path() メソッドにビューを提供できます。

また、プライマリキーは 'pk' で指定します。

views の修正

polls.views を書き換えます。

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from django.db.models import F

from .models import Choice, Question


class 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):
    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 = F('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,)))

各ビューに対応するクラスを、汎用クラスから派生させます。

IndexView は generic.ListView から派生されています。

ListView のデフォルトのテンプレート名は モデル名+_list + .html (_list は template_name_suffix 属性で定義された値) ですが、ここでは作成済のテンプレート名を template_name 属性で明示的に指定しています。また、コンテキスト変数名は、デフォルトでは モデル名+_list ですが、同様に context_object_name 属性で明示的に先に使用していた変数名を指定しています。

ListView

class django.views.generic.list.ListView

オブジェクトのリストを表示するページを表現する

[属性]
  • template_name: テンプレート名
  • context_object_name: コンテキストで使用する変数の名前を指定
  • template_name_suffix: 自動生成された候補テンプレート名に追加する接尾辞 (デフォルトは _list)
[メソッド]
  • get_queryset(): このビューの項目リストを取得する
  • get_context_object_name(): コンテキスト変数名を返す (デフォルトはモデル名+_list)

DetailView と ResultView は generic.DetailView から派生されています。

model 属性でモデルを指定し、template_name 属性でテンプレート名を指定しています。template_name_suffix 属性のデフォルト値が _detail なので、デフォルトのテンプレート名は モデル名 + _detail + .html になりますが、明示的に指定しています。

また、generic.DetailView でテンプレートに渡される変数名 (コンテキスト変数名) は、モデル名を小文字にしたものが自動的に使用されます。(get_context_object_name() で定義されている。)

DetailView

class django.views.generic.detail.DetailView

オブジェクトの詳細を表示するページを表現する

このビューが動作している間、self.object はビューが操作しているオブジェクトを含む

→ テンプレート上では、{{ object.フィールド名 }} として対象となるフィールド値にアクセスできる

[属性]
  • model: このビューが表示するモデル
  • template_name: テンプレート名
  • template_name_suffix: 自動生成されたテンプレート名候補に追加する接尾辞 (デフォルトは _detail)
[メソッド]
  • get_context_object_name(): コンテキスト変数名を返す (デフォルトはモデル名を小文字にしたもの)

参考

低価格なのに高速・多機能・高セキュリティ 月額400円(税別)から最大容量100GB WordPress専用高速サーバー Z.com WP
おすすめの記事