このページでは、Django におけるビュー(View)について解説していきます。
ここまで、Django・フレームワーク自体についての解説を下記ページで、

また、Django で開発するウェブアプリのファイル構成や動作の仕組みについて下記ページで解説を行なってきました。

ここまでは、主に Django の全体を理解していただくための解説をしてきましたが、ここからは Django における個別の機能や構成についての解説を解説を行なっていきます。
そして、今回解説するのがビューとなります。
Django で開発するウェブアプリの基本構造は MTV モデルとなっています。そして、この V の部分がビューとなります。このように、ビューは Django で開発するウェブアプリの基本構造の1つであり、ウェブアプリにおいて重要な存在となります。
また、ビューを上手く使いこなすためには URL とビューとのマッピング(関連付け)が重要となります。そのため、このページでは URL とビューとのマッピングについても解説していきます。
このページでは、特にビューの基本についてのみ解説を行いますが、ビューの基本をしっかり理解しておくことで、今後説明するテンプレートやフォーム・モデル等の使い方も理解しやすくなるため、是非このページで解説する内容は理解しておいてください。特に Django 初心者の方向けに詳しく・分かりやすく解説していきたいと思います。
ビューの基本
では、ビューについて解説していきます。
まず、Django におけるビューとは、一言で簡単に言えば「アプリの窓口」となります。
ビューはアプリの窓口
ウェブアプリとは、一言で言えばクライアント(ウェブブラウザ等)からのリクエストに応じた処理の実行およびレスポンスの返却を行うソフトウェアになります。
これは下記ページでも解説していますが、ウェブアプリは Django フレームワークとプロジェクトから構成されます。さらに、プロジェクトの中には複数のアプリが存在します。そして、ウェブアプリの中で最初にリクエストを受け取るのは Django フレームワークとなります。

そして、そのリクエストに応じて Django フレームワークからアプリの関数やメソッドが実行されることになります。この Django フレームワークから実行される関数やメソッドを提供するのが「ビュー」となります。さらに、実行された関数やメソッドはリクエストを受け取り、そのリクエストに応じたレスポンスを Django フレームワークに返却します。
ビューから Django フレームワークにレスポンスを返却すれば、Django フレームワークからウェブサーバー等を介してクライアントにレスポンスが返却されることになります。そして、そのレスポンスを受け取ったクライアントが、そのレスポンスに応じたページの表示等を行うことになります。
このように、クライアントからのリクエストがあった際に、Django フレームワークとの間でリクエストやレスポンスのやりとりを行うのはビューであり、ビューはアプリにおける窓口的存在であると言えます。
もう少し簡単に考えれば、Django フレームワークから利用される関数やクラス(メソッド)の定義を集めたものがビューであるとも言えます。
このページはビューの基本のみを解説していくため、ビューで定義するのは関数であることを前提に解説を進めていきたいと思います。関数ではなくクラスを定義するようにすることでビューをより簡潔に実装することができるようになるのですが、それについては応用編として別途解説ページを公開し、そこで詳細な説明をするようにしていきたいと思います。
スポンサーリンク
ビューの実装先は views.py
このビューの実装先は、プロジェクト内の各アプリに対して用意される views.py
となります。アプリ毎に views.py
を実装する必要があります。前述の通り、基本的に views.py
に実装するのは Django フレームワークから実行される関数(クラスやメソッド)となります。
下記ページでも解説していますが、views.py
は startapp
コマンドを実行することで自動的に生成されることになります。

views.py
を生成し、ビューを実装していく具体例は 掲示板アプリでビューを利用してみる の章で紹介していきたいと思います。
役割1:リクエストを受け取りレスポンスを返却する
前述の通りビューはアプリの窓口であり、アプリの窓口という責務を全うするために様々な役割を担うことなります。
まずビューは、Django フレームワークから利用される上で、最低限下記の条件を満たす必要があります。
- リクエストを受け取る
- レスポンスを返却する(or 例外を発生させる)
要は、ビューの関数は、Django フレームワークから引数としてリクエストを受け取り、さらに Django フレームワークにレスポンスを return
するように実装する必要があります(もしくは、エラーや問題が発生した際に例外を発生させる必要があります)。
この引数として受け取るリクエストとは HttpRequest
クラスのインスタンスであり、return
するレスポンスとは HttpResponse
クラスのインスタンスとなります。
より正確に言うと、ビューの関数が引数として受け取るリクエストは “HttpRequest
クラス、もしくは HttpRequest
のサブクラス” のインスタンスとなります
また、ビューの関数が返却するレスポンスとは “HttpResponse
クラス、もしくは HttpResponse
のサブクラス” のインスタンスとなります
次回以降の連載では、HttpResponse
のサブクラスを利用する例も示していきます
つまり、下記のように関数を定義すれば、最低限ですがビューの関数としては成立することになります。Django フレームワークからリクエストを引数 request
で受け取り、HttpResponse
のインスタンスを返却しているため(HttpResponse()
でインスタンスが生成される)、この index
関数は Django フレームワークから実行可能なビューの関数として成立しています。
from django.http.response import HttpResponse
def index(request):
return HttpResponse('Hello World!')
この index
関数から返却されたレスポンスは、Django フレームワークを介してウェブサーバーからクライアントに返却されます。このウェブサーバーからクライアントに返却されるレスポンスは下記のようなデータとなります。
HTTP/1.1 200 OK Date: Mon, 06 Feb 2023 20:45:16 GMT 〜略〜 Cross-Origin-Opener-Policy: same-origin Hello World!
1行目がレスポンスのステータスラインとなり、ここにリクエストに対する結果が記述されています。200
という数字は、リクエストに対する処理が正常終了したことを示すステータスコードとなります。この行は HttpResponse()
によってインスタンスを生成する際に自動的に設定されますし、HttpResponse()
の引数指定によってステータスコード等を変更することも可能です。
このページでは詳細な説明は行いませんが、ビューで例外を発生させた際には、その例外の内容に従って Django フレームワークが自動的にエラーとなるステータスコードやボディを設定してレスポンスするようになっています
また、”2行目 〜 最後の行の前の空白行” はヘッダーと呼ばれる部分で、ここにレスポンスの詳細が記述されています。ヘッダーに関しては、HttpResponse()
によってインスタンスを生成した際や、ビューから Django フレームワークに返却した後に情報が記述されていくことになります。
これらのステータスラインやヘッダーの情報は、HttpResponse
のインスタンスを生成した際や Django フレームワークに返却した後に、ある程度自動的に設定されることになります。
それに対し、ヘッダーの後ろの空白行の後はボディであり、ボディに関しては HttpResponse()
で引数で指定した文字列がそのまま設定されることになります。上記の例では 'Hello World!'
を指定しているためボディが単なる文字列になっていますが、本来であれば、このボディには HTML が設定されるように HttpResponse
のインスタンスを生成する必要があります。
Django の場合、この HTML の設定はテンプレートの仕組みを利用して行うことになります。このテンプレートについては下記ページの次回の連載で解説を行います。ひとまず、このページでは単なる文字列をボディとしてレスポンスするようにしていきたいと思います。

役割2:リクエストに応じた処理を行う
さて、先ほど示した index
関数は、ビューの関数として必要最低限な条件は満たしており、一応ビューの関数として完成していることになります。
ただ、このビューは Django フレームワークから実行可能となる最低限の条件を満たしているだけであり、ウェブアプリのビューとしてはまだ不十分です。具体的には、先ほど示した index
関数はリクエストを引数で受け取っているものの、リクエストを無視して単にボディが Hello World!
となるレスポンスを返却しているため、リクエストに応じた処理が行われていません。
本来、ビューは Django フレームワークから受け取ったリクエストに応じた処理を行う必要があります。そして、その処理結果に応じたレスポンスを返却する必要があります。
では、リクエストに応じた処理やレスポンスを実現するためにはどうすればよいでしょうか?
この点について、そもそもリクエストとは何なのか?という点を踏まえて説明していきたいと思います。
リクエストのデータ構造
まずはクライアントからウェブサーバーに送信されるリクエストのデータの中身を確認してみましょう!
リクエストのデータの中身の構造は下記のようになっています。
GET /index/ HTTP/1.1 Host: localhost:8000 〜略〜
1行目がリクエストラインとなります。このリクエストラインにリクエストの重要な情報が記載されており、その情報の1つ目が URL、2つ目がメソッドとなります。上記においては、/index/
が URL(ルートパス形式)であり、GET
がメソッドとなります。
クライアントから送信されてきたリクエストの内容の大部分は、この URL とメソッドにより決まります。
URL に応じた処理を行う
まず URL は、リクエスト先を示すデータとなります。例えば、このページであれば、下記の URL をウェブブラウザにアドレスバー等で指定することで表示することができます。
https://daeudaeu.com/django-view/
上記のような URL をウェブブラウザのアドレスバーに指定した際には、ウェブブラウザから daeudaeu.com
というドメインが運営されているサーバーに対し、URL が /dango-view/
となるリクエストが送信されます。
そして、リクエストを受け取ったサーバーは /dango-view/
へのリクエストに応じた処理を行い、結果として /dango-view/
のページを表示するための HTML 等がレスポンスとしてウェブブラウザに送信されることになります(そして、それを受け取ったウェブブラウザがページを表示する)。
また、下記の URL をウェブブラウザに指定した場合は、同様の動作で /dango-model/
のページを表示するための HTML 等がレスポンスとしてウェブブラウザに送信されることになります。この2つの例においてはリクエストの URL が異なるため、レスポンスとして送信される HTML も異なることになります。
https://daeudaeu.com/django-model/
このように、ウェブサイトでは、ユーザーはリクエスト先の URL によって表示したいページを指定できるようになっています。つまり、「ユーザーがやりたいこと(表示したいもの)」は URL によって指定されることになります。
実際には、ウェブブラウザのアドレスバーに URL を直接指定するのではなく、リンクやボタンをクリックすることでページを表示する機会が多いと思います。この場合も、リンクやボタンのクリック時に表示先の URL が設定されたリクエストが送信されるようになっており、結局 URL によってリクエスト先が決められるという点に変わりはありません。
また、上記の例はウェブサイト閲覧時のものになっていますが、ウェブアプリの場合も同様で、重要なのはリクエスト先の URL に応じて処理やレスポンスを変更する必要があるという点になります。
これを実現するため、Django のビューにおいては、指定される URL 毎に関数を用意し、関数毎に異なる処理の実行及びレスポンスの返却が行われるようにしておく必要があります。こうしておけば、ユーザーから指定された URL に応じた処理の実行・レスポンスの返却を実現することができます。
例えば、リクエストの URL が /login/
である場合にログインページを表示し、さらに /index/
である場合にウェブアプリのトップページを表示するようにウェブアプリを開発したい場合、ビューに login
関数と index
関数を用意する感じになります。
さらに、リクエストを受け取った際に、そのリクエストの URL に応じて実行する関数を振り分けるようにすれば、ユーザーからのリクエストの URL に応じた処理やレスポンスを実行することができるようになります。
先程の例であれば、リクエストの URL が /login/
である場合に login
関数を、/index/
である場合に index
関数をそれぞれ実行するように URL に応じた関数の振り分けを行います。
このように、リクエスト先の URL 毎に関数を用意し、リクエスト先の URL に応じて実行する関数を振り分けるようにすれば、リクエスト先の URL に応じた処理やレスポンスの返却を実現することができます。
この関数を用意するという点に関してはビューの役割になります。
それに対し、URL に応じて実行する関数を振り分けるのは Django フレームワークの役割となります。ただし、どの URL に対してどの関数を実行するかはウェブアプリ開発者が設定する必要があります。この設定を行なっておけば、その設定に基づいて Django フレームワークが実行する関数の振り分けを行ってくれるようになります。そして、この設定が、ページの題名にもある URL マッピングであり、この設定は urls.py
というファイルで行うことになります。これに関しては、後述の ビューと URL とのマッピング で詳細を解説します。
メソッドに応じた処理を行う
また、リクエストに含まれるもう1つの重要な情報がメソッドになります。
このメソッドは、リクエストの目的を示すデータになります。
多くの種類のメソッドが存在するのですが、まず覚えておくと良いのが GET
と POST
になります。
GET
はリクエストの目的がデータの取得であることを示すメソッドになります。ウェブページ表示時のリクエストは、ウェブページを表示するためのデータの取得を行うことが目的となりますので、この際のリクエストのメソッドとしては GET
が指定されます(実際にリクエストを受け取るのはウェブサーバー等になりますが、図ではそれらのウェブサーバーを省略しています)。
それに対し、POST
はリクエストの目的がデータの送信であることを示すメソッドになります。例えば掲示板などでコメントを投稿したい場合、リクエストの目的はコメントというデータの送信となりますので、この際のリクエストのメソッドとしては POST
が指定されます。
他にもユーザー登録やログイン等を行う際には、ユーザー名やパスワードなどをウェブアプリに送信することになるため、この際にも POST
が指定されることになります。
POST
メソッドによって送信されてきたデータをどう扱うかはウェブアプリや URL によって異なりますが、いずれにせよウェブアプリ側では送信されてきたデータを利用して処理を行うことが必要となります。
このように、リクエストではメソッドが指定されるようになっており、メソッドに応じてリクエストの目的が異なります。例えば同じ URL に対してリクエストを行ったとしても、メソッドによってユーザーのリクエストの目的は異なることになります。
そして、Django のビューにおいて重要なのは、このメソッドに応じた処理とレスポンスの返却を行う必要があるという点になります。
例えば、下の図のようなフォームでユーザー登録を行う場合の動作について考えてみましょう!このフォームのページは URL に /signup/
が指定された時に表示されるページとします。さらに、この /singup/
が指定された際にはビューの signup
関数が実行されるものとしたいと思います。
まず、このページでユーザー登録を行う際には、ユーザーはウェブブラウザでこのページを表示する必要があります。そのため、ページ表示のためのデータを取得するために、メソッドが GET
、URL が /signup/
のリクエストを送信することになります。そして、このページを表示するためのデータ(HTML)が取得され、ウェブブラウザに上の図のようなページが表示されることになります。
つまり、この singup
関数では、メソッドが GET
の時にフォームのページを表示するための HTML をレスポンスとして返却する必要があることになります。
さらに、ユーザーはユーザー登録を行うために、フォームにユーザー名やパスワードを入力し、それから登録ボタンを押すことになります。この際には、入力したユーザー名やパスワードがウェブアプリに対して送信されることになるため、リクエストのメソッドは POST
である必要があります。URL に関してはページ表示の時同様に /signup/
が指定されるものとしたいと思います。
そうなると、この場合も singup
関数が実行されることになります。ですが、先ほどとは異なりメソッドが POST
であり、ユーザーが入力したデータが一緒に送信されてくることになります。
もし、この場合にもメソッドが GET
の時と同じ処理を実行してしまうと、単に再度フォームが表示されるだけで、ユーザーの登録が行われないことになります。ユーザーの登録を行うためには、メソッドが POST
の場合には、送信されてきたデータを受け取り、さらにそれに応じてユーザーの登録を行うような処理が必要となります。
つまり、このような singup
関数では、メソッドが POST
の場合と GET
の場合とで処理を切り替え、メソッドに応じた処理を行う必要があることになります。このように、ビューの関数は、複数のメソッドのリクエストを受け取る可能性がある場合、それらのメソッドに応じて処理を切り替えるように実装する必要があります。
ただ、この実現方法は簡単です。ビューの関数で引数として受け取る HttpRequest
のインスタンスには、 method
データ属性にメソッドの種類が文字列としてセットされています。
したがって、下記のように if
文でメソッドの種類に応じて処理が分岐するようにしてやれば、リクエストに応じた処理を実現することが可能となります(下記ではメソッドが POST
の場合とそれ以外の場合とで分岐するようにしています)。
def signup(request):
if request.method == 'POST':
# メソッドがPOSTの場合の処理
return HttpResponse(〜略〜)
else:
# メソッドがPOST以外(GET)の場合の処理
return HttpResponse(〜略〜)
このように、views.py
に URL に応じた関数を定義しておき、さらに関数の中でメソッドに応じた処理の分岐を行うようにしておけば、リクエスト先の URL だけでなく、メソッドに応じた処理も行うことができるようになります。
ただし、全てのビューの関数でメソッドに応じた処理の分岐を行う必要もないです。例えば表示することのみが目的となる URL に対応するビューの関数においては、メソッドが GET
であることを前提に実装をしてやれば良いです。
それに対し、フォームを表示するようなページの場合、フォームを表示する際には GET
メソッドで、さらにフォームに入力したデータを送信する際には GET
メソッドでリクエストが送信されてくることになるため、メソッドが POST
である場合も考慮してビューの関数を実装しておく必要があります。
このフォームに関しては今後の連載における下記ページで解説を行ないます。ここで詳細を解説させていただきたいと思います。

リクエストの情報に応じた処理を行う
また、ビューの関数が受け取る HttpRequest
のインスタンスにはデータ属性として様々な情報がセットされていますので、これらの情報を利用することで開発できるウェブアプリの幅を広げることができます。
例えば、先程 POST
メソッドについて説明しましたが、POST
メソッドでのリクエスト時にはデータが送信されてくることになり、このデータはビューの関数が受け取る HttpRequest
のインスタンスのデータ属性 POST
にセットされています。
ですので、このデータ属性 POST
を利用すれば、ユーザーが送信してきたデータを保存したり、加工したりすることができ、これによって様々な機能実現することができるようになります。分かりやすい例で言えば、掲示板へのコメント投稿機能やログイン機能・ユーザー登録機能を実現するようなことも可能です。
また、ログイン機能をウェブアプリに持たせた場合、ビューの関数が受け取る HttpRequest
のインスタンスの user
データ属性にログイン中のユーザーの情報がセットされることになります。ですので、この user
データ属性を利用してログイン中のユーザーの情報を表示したりすることがもできるようになります。
このように、HttpRequest
のインスタンスにセットされている情報を利用することで、実現できる機能が増え、開発できるウェブアプリの幅も広げることができます。
これらのデータも含めて、リクエストに応じた処理・レスポンスの返却を行うことがビューの関数にとっては重要となります。
スポンサーリンク
役割3:モデルとテンプレートを適切に利用する
また、ビューの役割として重要なのが、モデルやテンプレートを適切に利用することになります。
ウェブアプリでは、リクエストを受け取った際にデータベースからデータを取得し、その情報を埋め込んだ HTML を生成してレスポンスとして返却することが多いです。
例えば、掲示板を表示するページに対する URL へのリクエストを受け取った際には、掲示板にすでに投稿されているコメントを取得し、その取得したコメントを埋め込んだ HTML をレスポンスとして返却します。こうすれば、その HTML を受け取ったウェブブラウザ側で、掲示板に投稿済みのコメントを表示することができます(この投稿済みのコメントはあらかじめデータベースに保存しておく必要があります)。
また、ウェブアプリでは、リクエスト受け取った際にデータベースへのデータの保存を行うことも多いです。
例えば、ウェブアプリにコメントを送信するリクエストを受け取った際には、そのコメントの内容をデータベースへ保存します。
こうしておけば、後からデータベースからコメントの内容を取得し、掲示板として各コメントの一覧を表示するようなことができるようになります。
このように、ウェブアプリでは、リクエストを受け取った際にデータベースの操作や、データベースから取得した情報を埋め込んだ HTML の生成が必要になるものが多いです。
これらのデータベースの操作や、データベースから取得した情報を埋め込んだ HTML の生成もビューだけで行うことも可能と言えば可能なのですが、これらもビューが行うことになるとビューの役割が多くなり、それに伴って views.py
のソースコードの分量が多くなってメンテナンス性が下がることになります。
ビューの役割が多くなりすぎることを防ぐため、Django にはビューの他にモデルとテンプレートが存在しています。簡単に言えば、モデルはデータベースの操作を行うことを役割とし、テンプレートは HTML の雛形を提供することを役割としています。
そのため、ビューからは直接データベースの操作を行う必要はありません。データベースの操作を行う際は、モデルに対して操作の依頼を行えば良いだけになります。つまり、モデルが提供するメソッドを実行すれば良いだけです。
ただし、モデルへの依頼内容はビューが決める必要があります。これは、実装的な観点で言えば、実行したいデータベースの操作に応じたメソッドの実行、さらには、そのメソッドへの引数の設定は views.py
で定義する関数に実装する必要があることを意味します。
また、HTML の雛形はテンプレートから提供されることになるため、ビューはその雛形に対して埋め込みたい情報を埋め込むだけで良いことになります。この HTML の雛形はファイルであり、このファイルのことをテンプレートファイルと呼びます。
また、テンプレートファイルへの情報の埋め込みは、Django フレームワークの提供する render
関数により実現することができます。この render
関数に「テンプレートファイルのパス」と「テンプレートファイルに埋め込みたいデータ(コンテキスト)」を引数に指定して実行すれば、返却値としてテンプレートファイルにデータを埋め込んだ結果の HTML をボディとするレスポンス(HttpResponse
のインスタンス)を取得することができます(実際には render
関数には HttpRequest
のインスタンスも指定する必要があります)。
つまり、ビューは、適切に引数を指定して render
関数を実行し、その返却値を return
するだけで、Django フレームワークに対してレスポンスを返却することができます。
ただし、テンプレートではテンプレートファイルを複数種類用意するケースが多いです。例えば特定のユーザーの詳細情報を表示するページと全ユーザーの一覧を表示するページではページの構造が異なるため、テンプレートファイルとしても別々に用意しておく必要があります。
そのためビューは、受け取ったリクエストに応えるために、複数存在するテンプレートの中から適切なものを選択する必要があります。そして、そのテンプレートファイルのパスを render
関数の引数として渡す必要があります。
また、テンプレートファイルに埋め込むデータを準備するのもビューの役割となります。このデータをコンテキストと呼びます。コンテキストはデータベースから取得したデータをセットして作成することが多いです。
このように、ビューはデータベースの操作や HTML の生成を行う際にモデルやテンプレートを利用することができます。これにより、役割をビューとモデルとテンプレートとで分担することができ、各部分の実装が簡潔になり、保守しやすくなります。
ただし、受け取ったリクエストによってデータベースへの操作内容やレスポンスとして返却したい HTML は異なるはずなので、リクエストに応じられるよう、ビューは適切に実行するモデルのメソッドや使用するテンプレートファイルの選択を行う必要があります。
ここではビューの役割という観点で説明を行いましたが、ここで登場したモデルやテンプレートに関しては後のほどの連載の中で説明をします。また、その際に、ビューからモデルやテンプレートを利用する際の実装例の紹介も行います。ですので、モデルやテンプレートに関しては今後の連載の中で理解していただくとして、このページでは、まずはビューの役割を理解しておいていただければ良いと思います。
ビューに関してのまとめ
ここまでビューの基本について解説してきました。
説明が長くなりましたので、ここで簡単にビューについてまとめておきます。
ビューは Django フレームワークに対するアプリの窓口になります。クライアントからウェブサーバーが受け取ったリクエストは、Django フレームワークを介してビューが受け取ることになります。さらに、ビューが Django フレームワークに対してレスポンスを返却することで、ウェブサーバーからクライアントに対してレスポンスが返却されることになります。
ビューの実装先は views.py
であり、この views.py
には関数やメソッドを実装する必要があります。Django フレームワークと上手くリクエストとレスポンスのやりとりを行うために、ビューの関数では最低限下記を行えるようにしておく必要があります。
- リクエストを受け取る
- レスポンスを返却する(or 例外を発生させる)
また、ビューはリクエストに応じた処理の実行とレスポンスの返却を行う必要があります。つまり、どんなリクエストを受け取ったとしても同じ処理の実行と同じレスポンスの返却を行うように実装するのではなく、リクエストに応じて実行する処理の内容や返却するレスポンスが切り替えられるようにしておく必要があります。
より具体的には、リクエストには URL とメソッドが指定されるため、その指定された URL とメソッドに応じた処理を行うように views.py
に対して関数やメソッドを実装する必要があります。
指定された URL に応じた処理は、例えば views.py
に指定可能な各 URL に応じた関数を用意しておき、さらに指定された URL に応じて実行する views.py
の関数を振り分けるようにすることで実現することができます。
views.py
の関数を実行するのは Django フレームワークであり、この Django フレームワークから実行される views.py
の関数の振り分けを実現するために必要な設定が URL のマッピングとなります。これについては、次の ビューと URL とのマッピング で解説したいと思います。
また、指定されたメソッドに応じた処理は、views.py
に用意した関数の中でメソッドに応じた処理の分岐を実装することで実現することができます。
URL やメソッドだけでなく、ビューの関数が受け取るリクエストには様々な情報が含まれます。これらの情報を上手く利用することで、開発可能なウェブアプリの幅を広げることができます。例えば POST
メソッドで送信されてきたデータやログイン中のユーザーの情報などを利用することが可能です。
さらに、ビューはリクエストに応じた処理やレスポンスの返却を行う際、データベースの操作や HTML の生成を行う必要があります。これらは、モデルやテンプレートの利用によって実現することが可能であり、ビューはこれらのモデルやテンプレートを適切に利用してリクエストに応じた処理やレスポンスの返却が行えるように実装する必要があります。
以上が、ビューの基本のまとめになります。
ただ、ここまでの解説はあくまでもビューの基本的な説明であって、別に上記の実装に拘る必要はありません。
例えば、ビューは関数を用意するのではなくクラスを用意することで実現することもできます。そして、Django フレームワークに用意されているクラスを継承して作成することで、実装が楽になったりします。
より具体的には、Django フレームワークには Views
というクラスが用意されており、これを継承することでリクエストのメソッドに応じて実行されるビューのメソッドを自動的に振り分けることもできるようになります。つまり、1つのビューの関数の中でリクエストのメソッドに応じた処理の分岐を行う必要はなく、リクエストのメソッドごとにクラスのメソッドを用意することで、リクエストのメソッドに応じた処理の実行の実現を行うことが可能となります(リクエストにもクラスにもメソッドがあって文章がちょっと複雑ですね…)。
こういったクラスをベースとしたビューの作り方についても別途ページを公開して解説していきたいと思います。まず、このページでは、ビューの役割や関数をベースとしたビューの作り方を理解していただければと思います。
ビューと URL とのマッピング
さて、ここまで解説してきたように、ビューはリクエストに応じた処理やレスポンスの返却を行う必要があります。そして、リクエストでは URL が指定されるため、URL に応じた処理やレスポンスの返却を行う必要があることになります。
これを実現する方法の1つは、指定可能な各 URL に応じた関数を views.py
に定義し、URL に応じて実行する views.py
の関数を振り分けることになります。
スポンサーリンク
関数と URL とのマッピングの必要性
そして、この views.py
の関数の実行を行うのは Django フレームワークとなります。ウェブブラウザ等のクライアントからリクエストを受け取った際に、Django フレームワークが自動的に views.py
の関数を実行してくれます。
ただし、受け取ったリクエストの URL に応じて実行する views.py
の関数を適切に振り分けるようにしてもらうためには、あらかじめ URL と views.py
の関数とのマッピングを行ない、それを Django フレームワークに指定しておく必要があります。
マッピングとは関連付けや紐付けなどの意味があり、URL のマッピングとは、下の図のように各 URL と views.py
の関数を関連付ける設定のことを言います。
このようなマッピングを行なっておけば、Django フレームワークがリクエストを受け取った際、その URL にマッピングされた関数が実行されるようになります。
Django では “URL” と関数とのマッピングだけでなく、”URL パターン” と関数とのマッピングを行うことも可能です
最初はマッピングを行うのが URL であることを前提に解説していきますが、後述で URL パターンと関数とのマッピングについても解説していきます
urls.py
で URL と関数とをマッピングする
そして、この URL と関数とのマッピングを行うためのファイルが urls.py
というファイルになります。
この urls.py
は、Django のプロジェクトを作成する際に自動的にプロジェクト設定フォルダ内に生成され、Django フレームワークから読み込まれて利用されるファイルとなります。
プロジェクトやプロジェクト設定に関しては前回の連載で解説していますので、これらの関係性を知りたい方は下記ページを読んでみてください。

urls.py
で行うことは urlpatterns
というリストの定義となります。このリストの1つ1つの要素で URL と関数とのマッピング設定を指定していくことになります。そして、urlpatterns
を定義しておけば、各要素で指定された URL へのリクエストを Django フレームワークが受け取った際、その URL にマッピングされた関数が実行されるようになります。
したがって、ウェブアプリに指定可能な URL に対応する分だけ urlpatterns
のリストの要素としてマッピング設定を指定しておけば、Django フレームワークがそれらの URL を受け付け、それに応じた関数の実行を行うことができるようになります。
URL と関数とのマッピング方法
続いては、この URL と関数とのマッピングの具体的方法について解説していきます。
urlpatterns
の各要素にマッピングを指定する
前述の通り、urls.py
はプロジェクト作成時にプロジェクト設定フォルダ内に自動的に生成されるファイルになります。自動生成後の urls.py
は下記のようなものになります(最初の """
〜 """
で囲まれた部分はコメントなので省略しています)。
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
上記のように、urls.py
が自動生成された時点で urlpatterns
が既に用意されており、この urlpatterns
の各要素に対してマッピング設定を指定していくことになります。
既に urlpatterns
の1つ目の要素として下記が指定されていますが、これもマッピング設定の1つであり、/admin/
から始まる URL に対するリクエストを受け取った際に管理画面のページを表示するためのマッピング設定となります。
path('admin/', admin.site.urls)
ウェブアプリにおいて管理画面は便利な機能なので、特に理由がなければ上記の1つ目の要素はそのまま残しておくと良いと思います。
ということで、2つ目の要素以降に自身のウェブアプリで受け付ける URL に対してマッピング設定を指定していくことになります。基本的には、上記の1つ目の要素の指定の仕方と同様の方法でマッピング設定を指定することになります。つまり、2つ目の要素以降に path
関数を指定していくことになります。
マッピング設定を path
関数により生成する
この path
関数は、引数に指定されたパラメータに応じたマッピング設定を生成する関数になります(具体的には、path
関数の返却値は URLPattern
や URLResolver
というクラスのインスタンスになるのですが、このページでは “マッピング設定” という言葉で説明をしていきます)。
そして、マッピング設定を生成するにあたって path
関数に最低限指定する必要のある引数は route
と view
になります。
path(route, view)
route
にはウェブアプリがリクエストを受け付ける URL を「ルートパス形式」で指定します(単なる URL だけでなく URL パターンを指定することも可能です。これについては後述で解説します)。ルートパス形式の URL とは、簡単に言えば URL における「ドメイン名よりも後ろ側の部分」になります。ただし、引数 route
には最初の /
を飛ばして指定する必要があります。例えば、下記の場合は app1/user/
を指定することになります。
さらに view
には、route
で指定された URL に対するリクエストを受け取った際に Django フレームワークに実行してほしい関数(関数オブジェクト)を指定します。
この route
と view
を指定して path
関数を実行すれば、引数に応じた URL と関数とを紐づけるためのマッピング設定が生成され、path
関数から返却されることになります。あとは、この返却値を urlpatterns
に格納しておけば、Django フレームワークが urlpatterns
の各要素に指定されたマッピング設定に基づき、URL に応じた関数の実行を行ってくれるようになります。
実際には、urlpatterns
の各要素には path
関数の返却値を指定するのではなく、path
関数自体を指定することになります。こうしておけば、Django フレームワークから urls.py
が読み込間れる際に path
関数が実行され、 urlpatterns
の各要素に path
関数の返却値であるマッピング設定がセットされることになります。
つまり、URL と関数とのマッピングは、マッピングしたい「URL」と「関数」を引数に指定した状態の path
関数を urlpatterns
の各要素として記述しておくことで実現することができます。
from django.urls import path
urlpatterns = [
path(route1, func1),
path(route2, func2)
path(route3, func3)
]
これにより、クライアントからリクエストされた URL に対するマッピング設定が urlpatterns
内に存在する場合、その URL にマッピングされた関数が実行されることになります。
クライアントからリクエストされた URL に対するマッピング設定が urlpatterns
内に存在しない場合は、関数を実行することなく Django フレームワークが Page not found
エラー(404
エラー)を返却することになります。つまり、ウェブアプリに指定可能な URL は、マッピング設定を行なった URL のみとなります。
マッピングの実装例
例えば、/index/
という URL へのリクエストを受け取った際にビューの index
関数が、さらに /user/
という URL へのリクエストを受け取った際にビューの user
関数がそれぞれ実行されるようにしたい場合は、下記のようにurls.py
を変更すれば良いことになります(コメント部分は省略します)。
from django.contrib import admin
from django.urls import path
from アプリ名 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index)
path('user/', views.user)
]
ポイントは、ビューの関数はアプリの views.py
で定義されるため、上記の3行目のように、その views.py
をインポートしてから path
関数の引数でビューの関数を指定する必要があるという点になります。
アプリの urls.py
に分離する
上記のように、プロジェクト設定フォルダの urls.py
を書き換えてやることで URL と関数のマッピングを行うことは可能なのですが、実は上記のようにプロジェクト設定フォルダの urls.py
のみで urlpatterns
の全要素を指定するような書き方は推奨されていません。
実際には、アプリフォルダ内にも urls.py
を用意し、各アプリで受け付ける URL に対するマッピング設定に関しては、そのアプリフォルダ内の urls.py
で指定することが推奨されています。アプリフォルダ内の urls.py
においても、今までの説明と同様に urlpatterns
の各要素にマッピング設定(path
関数の返却値)を指定を行うことで各 URL に対する関数のマッピングを行います。
ただし、Django フレームワークからはアプリフォルダ内の urls.py
は直接読み込まれません。Django フレームワークが直接読み込む urls.py
はプロジェクト設定フォルダ内のもののみになります。そのため、プロジェクト設定フォルダ内の urls.py
が読み込まれた際に、プロジェクト設定フォルダ内の urls.py
から各アプリフォルダ内の urls.py
が読み込まれるようにしておく必要があります。
このアプリの urls.py
の読み込みは、path
関数の引数 view
に対して include('アプリ名.urls')
を指定することにより実現できます。
path('アプリに対応するURL/', include('アプリ名.urls')),
例えば、プロジェクト内にアプリ名 app1
のアプリとアプリ名 app2
のアプリが存在する場合は、アプリ名.urls
の部分にはそれぞれ app1.urls
と app2.urls
を指定することになります。
上記のように引数を指定した path
関数をプロジェクト設定フォルダ内の urls.py
における urlpatterns
の要素に指定しておけば、プロジェクト設定フォルダ内の urls.py
が Django フレームワークから読み込まれる際、アプリ名.urls
、すなわち アプリ名
フォルダ内の urls.py
が読み込まれるようになります。
さらに、リクエスト先の URL が /アプリに対応するURL/
から始まる場合、読み込んだ アプリ名.urls
の urlpatterns
に指定されたマッピング設定に基づいて実行される関数が振り分けられるようになります。/アプリに対応するURL/
の部分は、分かりやすい名前であれば自由に決めて問題ありません(そのまま アプリ名/
とすることが多いと思います)。
例えば、先ほどと同様にプロジェクト内に app1
というアプリと app2
というアプリが存在するとします。この場合、まずはそれぞれのアプリのフォルダ内に urls.py
を作成します。今回は例として下記のような urls.py
を app1
と app2
の両方のフォルダの中に作成することとしたいと思います。
1行目では、from . import views
によって同じフォルダ内の views
を import
しています。
from . import views
from django.urls import path
urlpatterns = [
path('index/', views.index),
path('user/', views.user),
]
続いてプロジェクト設定フォルダ内の urls.py
を下記のように変更します。include
の import
が必要である点に注意してください。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('app_1/', include('app1.urls')),
path('app_2/', include('app2.urls')),
]
このように各 urls.py
を用意しておけば、Django フレームワークがプロジェクト設定フォルダ内の urls.py
を読み込んだ際に、app1.urls
(app1
フォルダ内の urls.py
)と app2.urls
(app2
フォルダ内の urls.py
)を読み込んでくれるようになります。この読み込みが行われるのは include
関数が実行されるからになります。
さらに、Django フレームワークがリクエストを受け取った際、そのリクエストの URL が /app_1/
から始まる場合、app1.urls
の urlpatterns
に従って実行する関数が振り分けられます。
より具体的には、URL が /app_1/index/
である場合、app1
内の views.py
で定義された index
関数が実行されます。また URL が /app_1/user/
である場合、app1
内の views.py
で定義された user
関数が実行されます。
同様に、リクエストの URL が /app_2/
から始まる場合、app2.urls
の urlpatterns
に従って実行する関数が振り分けられることになります。
このように、アプリ毎に urls.py
を用意し、プロジェクト設定フォルダ内の urls.py
からアプリ毎の urls.py
を読み込むようにすることで、プロジェクト全体が受け付ける全 URL に対して関数をマッピングしていくのが Django 公式からも推奨されているマッピングの方法となります。
実際、上記の例のマッピングであれば、プロジェクト設定フォルダの urls.py
を下記のように変更しても実現することが可能です。
from django.contrib import admin
from django.urls import path
from app1 import views as app1_views
from app2 import views as app2_views
urlpatterns = [
path('admin/', admin.site.urls),
path('app_1/index/', app1_views.index)
path('app_1/user/', app1_views.user)
path('app_2/index/', app2_views.index)
path('app_2/user/', app2_views.user)
]
ただし、受け付ける URL が多くなるとプロジェクト設定フォルダ内の urls.py
への記述量が多くなり、ソースコードが読みにくくなりますし、またプロジェクトとアプリの依存性が高くなり、アプリの他のプロジェクトへの流用もしにくくなります。
これらを解決するのが、ここで紹介したアプリ毎に urls.py
を分離する方法になります。1つ1つの urls.py
への記述量が減るのでソースコードが読みやすくなりますし、各アプリのマッピング設定はアプリフォルダ内の urls.py
で指定されるのでプロジェクトとアプリの依存性も減ります。
こういったメリットがありますので、マッピング設定はアプリ毎に分離して指定するようにしたほうが良いです。
スポンサーリンク
URL に名前を付ける
さて、ここまでの説明のように、path
関数に route
と view
を指定することで URL と関数のマッピングを行うことが可能です。path
関数へは URL と関数のマッピングを行うために route
と view
は必ず指定する必要があります。
path
関数への name
引数の指定
また、path
関数には name
引数を指定することができ、name
引数に名前を指定することで、route
に指定する URL に名前を付けることができます。
path(route, view, name='名前')
この name
引数で指定する名前を URL 名
と呼ばせていただきます。上記のように path
関数で name
引数を指定して URL に URL 名
をつけた場合、この URL 名
から URL を逆引きして取得するようなことができるようになります。
例えば、先程の説明時に利用した app_1/urls.py
に下記のように記述すれば、name
に指定した 'app_1-top'
から URL /app_1/index/
を取得することができるようになります。
path('index/', views.index, name='app_1-top')
URL 名
をつけるメリット
続いて、この name
引数の指定によって URL 名
をつけるメリットについて解説していきます。
結論を言うと、このメリットは「後から URL の変更が楽になる」という点にあります。
例えば、ウェブにはリダイレクト機能が存在し、この機能によって特定の URL にリクエストを行なったクライアントを別の URL に誘導することができるようになっています。
このリダイレクトは、Django においてはビューの関数から redirect
関数の返却値を返却することで実現できます。redirect
関数では引数に誘導先の URL や URL 名
を指定することができます(他にも関数オブジェクトも指定可能ですが、その説明は省略します)。
つまり、上記の例のように path
関数でマッピングした場合、/app_1/index/
への誘導を行うための redirect
関数への引数の指定の仕方としては、例えば下記のパターンが存在することになります。
from django.shortcuts import redirect
return redirect('app_1-top')
from django.shortcuts import redirect
return redirect('/app_1/index/')
前者の場合、URL 名
から URL が逆引きされ、その URL へのリダイレクトが行われることになります。
前者・後者のどちらでもリダイレクトを実現することは可能なのですが、推奨される方法は前者の URL 名
を指定する方法になります。これは、URL 名
で指定を行った方が、後から URL の変更が必要になった際の修正が楽になるからです。
ウェブアプリでは自身のウェブアプリが受け付ける URL を様々な場面で指定することになります。上記のリダイレクトはその例の1つで、例えばテンプレートファイルでも他のページへのリンクを設定するのに URL を指定する必要があります。そして、こういった URL の記述は URL 名
でも代替することが可能となります。
URL 名
ではなく URL を直接指定していた場合、もし後から URL を変更するようなことになれば、その URL を指定している箇所全てを修正する必要があります。
ですが、URL 名
で指定していた場合、URL を変更したとしても変更が必要な箇所は urls.py
のみとなります。urls.py
に記述する URL を変更してやれば、あとは URL 名
から逆引きした際に変更後の URL に変換されることになります。
つまり、URL 名
を付けておき、ウェブアプリ内のスクリプトやテンプレートファイルに URL ではなく URL 名
を指定するようにしておけば、後から URL を変更したくなった際にも楽に変更を行うことができます。この変更が楽な点を考慮すると、URL を直接指定するのは urls.py
のみとし、あとは URL 名
で指定するようにした方が良いです。
URL の一部を引数に指定する(URL のパターン化)
ここまでの説明の通り、urls.py
を適切に作成しておくことで、Django フレームワークがリクエストを受け取った際に urls.py
に従って URL に応じてビューの関数が実行されるようになります。
ただ、おそらく皆さんもご存知の通り、関数を実行する際には引数が指定されることがあります。では、Django フレームワークがビューの関数を実行する際には、どのような引数が指定されることになるのでしょうか?
URL の一部を引数としてビューに渡す
ここまでの解説でも何回か説明しましたが、ビューの関数には必ず HttpRequest
のインスタンスが引数指定されます。基本的には、この HttpRequest
のインスタンスのみが引数に指定されることになります。
ですが、Django では urlpatterns
の各要素における path
の route
引数への URL の指定方法によって、URL の一部を引数としてビューの関数に渡すことができるようになります。つまり、ビューの関数に指定される引数を増やすことができます。
具体的には、path
関数の route
引数に指定する URL において、変数としてビューの関数に渡して欲しい URL の部分を <型名:引数名>
という形式で記述することで、リクエストされた URL の <型名:引数名>
部分がビューの関数の引数 引数名
に指定されるようになります。
例えば、プロジェクト設定フォルダの urls.py
を下記のように記述し、
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('app_1/', include('app1.urls')),
]
さらに、app1
のアプリの urls.py
を下記のように記述したとしましょう。
from . import views
from django.urls import path
urlpatterns = [
path('index/', views.index),
path('user/<str:username>/', views.user)
]
このように各 urls.py
を作成した場合、リクエストの URL が /app_1/user/文字列/
の形式である際には、同じアプリ内の views.py
で定義されている user
関数(views.user
)が実行され、その際に 文字列
の部分が引数 username
に指定される形で user
関数に渡されることになります。
例えば、下記の URL へのリクエストがあった場合は、user
関数が実行され、その際に引数 username
に文字列 'YamadaHanako'
が指定されることになります。
/app_1/user/YamadaHanako/
同様に、下記の URL へのリクエストがあった場合は、user
関数が実行され、その際に引数 username
に文字列 'YamadaTaro'
が指定されることになります。
/app_1/user/YamadaTaro/
つまり、URL に応じて関数の引数に渡されるデータが変化することになります。例えば、下記のように user
関数を定義しておけば、print
関数で出力される文字列は URL に応じて変化することになります。
def user(request, username):
print(username)
# 略
このように、path
の route
引数に指定する URL において、変数としてビューの関数に渡して欲しい URL の部分を <型名:引数名>
という形式で記述しておけば、実行されるビューの関数に引数として情報を渡すことができるようになります。
URL のパターン化
また、route
引数に指定する URL の一部を <型名:引数名>
と記述することで、ウェブアプリが受け付ける URL のパターン化が行えるようにもなります。要は、1つの path
関数によるマッピング設定が、特定の1つの URL に対してだけでなく、パターンに当てはまる全ての URL に対して適用されるようになります。
例えば下記の形式の URL をリクエストされた際に ユーザー名
で指定されたユーザーの詳細情報を表示する例で考えてみましょう。
/app_1/user/ユーザー名/
URL のパターン化を行わない場合、各ユーザーの詳細情報を表示するための URL に対して個別にマッピング設定を行う必要があるため、ウェブアプリにユーザー登録している全ユーザー分の URL を path
の route
引数に指定する必要があります。
from . import views
from django.urls import path
urlpatterns = [
path('user/YamadaHanako/', views.user),
path('user/YamadaTaro/', views.user),
path('user/TakahashiJiro/', views.user),
path('user/SatoSaburo/', views.user),
path('user/TanakaShiro/', views.user),
〜略〜
]
しかし、path
の route
引数に URL のパターンを指定すれば、全ユーザー分の URL を1つのマッピング設定(path
関数)で完結することができます。
from . import views
from django.urls import path
urlpatterns = [
path('user/<str:username>/', views.user),
]
このように、path
の route
引数に指定する URL の一部を<型名:引数名>
とすることで URL のパターン化を行うことができ、1つの path
関数により複数の URL に対応することができます。さらに、<型名:引数名>
の部分はビューの関数で引数として受け取ることができるようになります。
また、<型名:引数名>
の 型名
に指定できるのは、ここまで利用してきた str
だけでなく int
なども指定可能です。<型名:引数名>
の 型名
に指定可能なものの一覧は下記の Django の公式チュートリアルから確認可能です。
https://docs.djangoproject.com/en/4.1/topics/http/urls/#path-converters
引数名
には基本的に好きなものを指定して良いですが、ビューの関数の他の引数と被らないようにする必要があります。また、引数名
に指定した引数はビューの関数の引数に用意しておく必要があるので注意してください。
また、URL のパターン化は正規表現などでも実現可能です。ただ、上記のように <型名:引数名>
によるパターン化が一番簡単だと思いますので、まずはこの方法でのパターン化を覚えておくと良いと思います。
掲示板アプリでビューを利用してみる
ビューや URL のマッピングに関する解説は以上となります。
続いては、今までの復習の意味も込めて、実際に views.py
や urls.py
の実装を行なっていきたいと思います。
この Django 入門に関しては連載形式の解説としており、この連載を通じて簡単な「掲示板ウェブアプリ」を開発していこうと思います。今回は、この掲示板ウェブアプリにおける views.py
と urls.py
の実装を行い、ビューの作成と URL のマッピングを行なっていきます。
ただし、今回解説した内容はビューと URL マッピングのみですので、これだけで実現できるウェブアプリはとても掲示板とは呼べないものになります…。ですが、今後、Django の様々な要素や機能について解説を行い、それらの実装を加えていくことで、それなりの掲示板ウェブアプリを開発することができます。開発を通して様々なことが学べると思いますので、是非掲示板ウェブアプリの開発にも取り組んでみていただければと思います。
また、今回は特に実装観点での解説ページの初回となりますので、プロジェクト・アプリの作成から解説をしていきます。
スポンサーリンク
事前準備:Django のインストール
もし、まだ Django のインストールをしていない方は、この機会に Django のインストールをしておきましょう!
Django は下記のように pip
を利用してインストールすることができます。
% python -m pip install django
アンインストールも pip
を利用すれば下記のように行うことができますので、不必要になればすぐに消すことも可能です。
% python -m pip uninstall django
プロジェクト・アプリの作成
では、プロジェクトとアプリを作成していきます。プロジェクトやアプリの意味合いについては下記ページで解説していますので、詳しく知りたい方は下記ページをご覧ください。

プロジェクトに関しては下記の形式のコマンドで作成することができます。
% django-admin startproject プロジェクト名
また、アプリは、上記コマンドで作成される プロジェクト名
のフォルダの中で下記の形式のコマンドで作成することができます。
% python manage.py startapp アプリ名
そして、これらのコマンドを実行すれば、プロジェクトやアプリに最低限必要なファイルが自動的に作成されることになります。
今回は、プロジェクト名は testproject
、アプリ名は forum
にしたいと思います。
ということで、まずは下記コマンドを実行してプロジェクトを作成します。これにより下記コマンドを実行したフォルダ内に testproject
というフォルダが作成されます。
% django-admin startproject testproject
次に、cd
コマンドで testproject
フォルダに移動し、
% cd testproject
さらに下記コマンドでアプリを作成します。
% python manage.py startapp forum
以上により、プロジェクトとアプリが作成され、アプリ開発に最低限必要なファイルやフォルダが作成されることになります。
プロジェクトの設定(アプリの登録)
続いて、プロジェクトの設定を行います。
先ほど cd
コマンドで testproject
フォルダに移動しましたが、そのフォルダの中にもう1つ testproejct
フォルダが存在するはずです。このフォルダには主にプロジェクトの設定を行うファイルが集められており、その1つのファイルとして settings.py
が存在します。
次は、この settings.py
を変更してプロジェクトの設定を行います。
アプリの登録
まずは、プロジェクトへのアプリの登録を行います。
プロジェクトに登録されているアプリは settings.py
で定義される INSTALLED_APPS
というリストで管理されており、このリストを変更することでプロジェクトに登録されているアプリを変更することが可能です。
今回はプロジェクトへのアプリの登録を行いますので、登録したいアプリを INSTALLED_APPS
に追加を行います。登録したいアプリは、先ほど作成した forum
となりますので、下記のようにリストに 'forum'
を追加します。これにより、プロジェクトにアプリ forum
が登録され、プロジェクト起動時に forum
の各種ファイルが読み込まれるようになります。
INSTALLED_APPS = [
'forum', # 追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
言語・タイムゾーンの設定
また、ウェブアプリで表示される言語や、ウェブアプリで扱う時刻のタイムゾーンについても settings.py
で設定可能です。これは別に必須ではないですが、今回は言語を日本語、タイムゾーンも日本時間に変更したいと思います。
言語に関しては settings.py
の LANGUAGE_CODE
で、タイムゾーンに関しては settings.py
の TIME_ZONE
でそれぞれ設定することが可能ですので、これらを下記のように変更します。
LANGUAGE_CODE = 'ja' # 変更
TIME_ZONE = 'Asia/Tokyo' # 変更
スポンサーリンク
ビューの作成
続いて、このページの本題の1つであるビューを作成していきます。
ビューの例
前述の通り、このビューは views.py
への実装を行なって作成していくことになります。この views.py
は forum
フォルダ内に存在するはずです。今回は、views.py
を下記のように変更したいと思います。
from django.http import HttpResponse, Http404
from django.shortcuts import redirect
class User:
def __init__(self, id, username, email, age):
self.id = id
self.username = username
self.email = email
self.age = age
import datetime
class Comment:
def __init__(self, id, text, date):
self.id = id
self.text = text
self.date = date
users = [
User(1, 'Yamada Taro', 'taro@yamada.jp', 18),
User(2, 'Yamada Hanako', 'hanako@yamada.jp', 22),
User(3, 'Sato Saburo', 'saburo@sato.jp', 53),
User(4, 'Takahashi Shiro', 'shiro@takahashi.jp', 64)
]
comments = [
Comment(1, 'おはようございます', datetime.datetime(2023, 3, 4, 12, 4, 0)),
Comment(2, 'いい天気ですねー', datetime.datetime(2023, 4, 5, 16, 21, 0)),
Comment(3, '明日もよろしくお願いします', datetime.datetime(2000, 12, 25, 1, 55, 0)),
Comment(4, 'おやすみなさい', datetime.datetime(2024, 1, 1, 1, 37, 0)),
Comment(5, '山路を登りながら、こう考えた。智に働けば角が立つ。情に棹させば流される。意地を通とおせば窮屈だ。とかくに人の世は住みにくい。', datetime.datetime(2012, 10, 8, 3, 49, 0)),
]
def index_view(request):
return redirect('comments')
def users_view(request):
body = ''
for user in users:
body += '<a href="/forum/user/{id}/">{name}</a>'.format(id=user.id,name=user.username)
body += '\n<br>'
return HttpResponse(body)
def user_view(request, user_id):
if user_id > len(users) or user_id < 1:
raise Http404('Not found user')
body = ''
user = users[user_id - 1]
body += user.username
body += ','
body += user.email
body += ','
body += str(user.age)
body += '\n<br>'
return HttpResponse(body)
def comments_view(request):
body = ''
for comment in comments:
body += '<a href="/forum/comment/{id}/">{text}</a>'.format(id=comment.id,text=comment.text)
body += '\n<br>'
return HttpResponse(body)
def comment_view(request, comment_id):
if comment_id > len(comments) or comment_id < 1:
raise Http404('Not found comment')
body = ''
comment = comments[comment_id - 1]
body += comment.text
body += ','
body += '{0:%Y年%m月%d日}'.format(comment.date)
body += '\n<br>'
return HttpResponse(body)
ビューの説明
この views.py
には5つの関数を定義しており、それぞれの役割を簡単に書くと下記のようになります。
index_view
:トップページを表示する(リダイレクトするだけ)users_view
:ユーザー一覧ページを表示するuser_view
:特定のユーザーの詳細情報ページを表示するcomments_view
:投稿済みコメント一覧ページを表示するcomment_view
:特定のコメントの詳細情報ページを表示する
ユーザーはリスト users
で管理しており、コメントはリスト comments
で管理しています。さらに、各ユーザーは User
クラスのインスタンスとして、各コメントは Comment
クラスのインスタンスとして扱うようにしています。
また、User
クラスの各インスタンスには id
(ID)・username
(名前)・email
(メールアドレス)・age
(年齢) を、Comment
クラスの各インスタンスには id
(ID)・text
(本文)・date
(投稿日時) を設定できるようにしています。
ユーザーやコメントは事前にリストで用意していますが、フォームを利用することで、ユーザーの登録やコメントの投稿をユーザーが行えるようになります。また、モデルを利用することで、これらのユーザーやコメントをデータベースで管理できるようになります(データベースで管理するために、上記で説明した各クラスは、モデルクラスに置き換えることになります)。
ですが、フォームやモデルについてはまだ説明していないため、まずは事前にリストで用意したものを利用してビューの働きだけを確認できるようにしています。
また、上記の5つの関数は、リクエストが GET
メソッドであることを前提とした作りになっています。前述の通り、リクエストには POST
メソッドのものも存在しますが、これに関してもフォームの説明をした後に実装例を紹介するようにしたいと思います。
さらに、index_view
以外の関数では、自身の関数の中で HTML を生成し、それをボディとするレスポンスを返却するようになっています(例外が発生しない限り)。これらの HTML の生成に関しては、これも前述の通り、基本的にはテンプレートを利用して実現することになり、これによって各種関数がもう少しスッキリすることになります。
続いて、これらの5つのビューの関数のポイントを説明していくと、1つ目のポイントは全ての関数が下記を満たしている点となります。
- リクエストを受け取る
- レスポンスを返却する(or 例外を発生させる)
全ての関数は引数を受け取るようになっており、第1引数 request
で Django フレームワークからリクエストを受け取るようになっています。
また、users_view
と comments_view
に関しては必ず HttpResponse
のインスタンスをレスポンスとして返却するようになっています。さらに、user_view
と comment_view
に関しても、基本的には HttpResponse
のインスタンスをレスポンスとして返却するようになっているのですが、引数で指定された user_id
や comment_id
に対応するユーザーやコメントが存在しない場合は Http404
の例外を発生させるようになっています。
index_view
の場合は redirect
関数の返却値を返却することになりますが、redirect
関数の返却値は HttpResponsePermanentRedirect
or HttpResponseRedirect
のクラスのインスタンスとなり、どちらも HttpResponse
のサブクラスであるため、index_view
もレスポンスを返却することになります。
これらの例のように、ビューの関数は必ずレスポンスの返却 or 例外の発生を行う必要がある点がポイントになります。
2つ目のポイントは、user_view
と comment_view
が request
以外の引数を受け取るように作られている点になります。したがって、URL の一部を引数に指定する(URL のパターン化) で解説した内容に従い、request
以外の引数を Django フレームワークから受け取れるように urls.py
を作成する必要があります。
3つ目のポイントとなるのは index_view
で実行している redirect
関数の引数で、この引数には URL の名前を指定しています。具体的には comments
という名前を指定しています。したがって、URL に名前を付ける で解説した内容に従い、urls.py
で何らかの URL には comments
という名前をつけておく必要があります。
特に2つ目と3つ目のポイントに関しては主に urls.py
に対するポイントでもあるのですが、大事なのは views.py
と urls.py
は特に関係性が高く、これらの両方で話が合うように作成する必要がある点になります。
これらのポイントを踏まえた上で、続いて urls.py
の変更・作成を行なっていきたいと思います。
URL のマッピング
ビューは作成したものの、ビューは単に作成しただけでは Django フレームワークから実行されません。
前述の通り、URL とビューのマッピングを行う必要があります。
ということで、このマッピングを行うため、次は urls.py
を作成していきたいと思います。今回はアプリ側にも urls.py
を用意し、プロジェクト側の urls.py
からアプリ側の urls.py
を読み込むようにすることでマッピングを実現していきます。
アプリの urls.py
の作成
まずは、forum
フォルダの中に urls.py
を作成し、中身を下記のように変更してください。
from django.urls import path
from . import views
urlpatterns = [
path('', views.index_view, name='index'),
path('comments/', views.comments_view, name='comments'),
path('comment/<int:comment_id>/', views.comment_view, name='comment'),
path('users/', views.users_view, name='users'),
path('user/<int:user_id>/', views.user_view, name='user'),
]
プロジェクトの urls.py
の変更
さらに、testproject
フォルダの中にある urls.py
を下記のように変更します。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('forum/', include('forum.urls'))
]
マッピングによるアプリの動作
これにより、URL が /forum/
から始まるリクエストを Django フレームワークが受け取った際、Django フレームワークが forum
フォルダの urls.py
を読み込むようになります。そして、リクエストされた URL の /forum/
よりも後ろ側の部分のパスに応じて実行されるビューの関数が振り分けられるようになります。
具体的には、リクエストされた URL (ルートパス形式) に対し、Django フレームワークから実行されるビューの関数は下記のようになります。
/forum/
:index_view
/forum/comments/
:comments_view
/forum/comment/
:comment_view
/forum/users/
:users_view
/forum/user/
:user_view
特にポイントになるのが /forum/comment/
と /forum/user/
に対する URL とビューの関数とのマッピングで、これらの URL に対応する comment_view
と user_view
では引数を受け取るようになっています。そのため、URL の一部を関数の引数として受け取れるよう、forum
フォルダの urls.py
におけるこれらの URL のマッピングにおいては、URL の一部を <型名:引数名>
という形式で記述しています。
例えば、/forum/comment/
に対する URL マッピングの設定は下記のようになっており、リクエストされた URL が /forum/comment/
から始まる場合、/forum/comment/
の後ろ側の整数が views.py
における comment_view
に引数 comment_id
として渡されるようになります。
path('comment/<int:comment_id>/', views.comment_view, name='comment'),
また、各マッピングを行うために実行する path
関数では name
を設定するようにしており、これによって URL に名前がつけられることになります。今回は index_view
で実行する redirect
関数の引数に、URL の名前である 'comments'
を指定していますので、この redirect
関数の実行によって、comments
の名前に対応する URL の /forum/comments/
にリダイレクトするためのレスポンスが Django フレームワークに返却されることになります。
今回は URL の名前を利用している箇所が1つのみとなりますが、次の連載で説明するテンプレートを導入すると、頻繁に利用するようになります。
動作確認
最後に動作確認を行なっておきましょう!
開発用ウェブサーバーの起動
まずは、ウェブアプリにアクセスできるよう、Django 開発用ウェブサーバーを起動します。この開発用ウェブサーバーの起動は、manage.py
が存在するフォルダ(プロジェクトの testproject
フォルダの中)で下記コマンドを実行することで実現できます。
% python manage.py runserver
これにより、ウェブブラウザ等のクライアントからリクエストを受け取るウェブサーバーが起動することになります。
コメントの表示の確認
ということで、次はウェブブラウザを開き、アドレスバーに下記 URL を指定します。
http://localhost:8000/forum/comments/
これにより、ウェブブラウザ(クライアント)から上記で示した localhost
という名前のサーバーに対して接続が行われ、さらに /forum/comments/
の URL に対してリクエストが送信されることになります。この時のリクエストのメソッドは GET
になります。
また、localhost
は自分自身の PC を指しており、この PC では runserver
の実行により開発用ウェブサーバーが動作してクライアントからのリクエストを待ち受けています。そして、上記のリクエストが送信されてくると、開発用ウェブサーバーがリクエストを受け取り、Django フレームワークを介して /forum/comments/
にマッピングされた関数、すなわち views.py
の comments_view
が実行されます。さらに、comments_view
が実行されてレスポンスを返却すると、Django フレームワークを介して開発用ウェブサーバーからクライアントに対してレスポンスが返却されることになります。
レスポンスを受け取ったウェブブラウザは、レスポンスのボディ等に応じてページを表示します。上記の URL をアドレスバーに指定した場合は、下図のようなページが表示されるはずです。
このページはコメント一覧を示すページとなっており、各コメント文がリンクとなっています。リンクをクリックすれば、先ほどと同様の流れで /forum/comment/id/
にリクエストが送信されます。この場合は、views.py
の comment_view
関数が実行されることになり、id
の部分の整数が引数 comment_id
として渡されることになります。また、id
部分はコメントの ID を示す整数で、リンクごとに異なる値が設定されるようになっています。
そのため、リンクのクリックにより、クリックしたリンクに応じたコメントの詳細ページが表示されることになります。
ユーザーの表示の確認
同様に、下記の URL をウェブブラウザのアドレスバーに指定すれば、
http://localhost:8000/forum/users/
今度は users_view
が実行され、下の図のようなユーザー一覧ページが表示されることになります。
さらに、これも先ほどと同様にユーザー名をクリックすれば、今度は /forum/users/id/
に対してリクエストが送信されることになり(id
はユーザーの ID)、user_view
が実行され、クリックしたユーザーに応じたユーザーの詳細情報が表示されるようになっています。
また、下記をアドレスバーに指定した場合は、index_view
が実行されることになり、この場合は /forum/comments/
にリダイレクトされることになります。
http://localhost:8000/forum/
そのため、下記をアドレスバーに指定した時と同じページが表示されるはずです。
http://localhost:8000/forum/comments/
例外発生の確認
最後に例外発生時の動作を確認しておきましょう!まずは下記の URL をアドレスバーに指定してみてください。
http://localhost:8000/forum/comment/10/
この場合は、下図のようなページが表示されるはずです。
前述で示した views.py
において、管理しているコメント、すなわちリスト comments
の各要素に設定されている id
は 1
〜 5
のみです。そのため、comment_view
の引数 comment_id
にそれ以外の整数が指定された場合は、下記の if
文が成立して raise
により例外が発生するようになっています。
if comment_id > len(comments) or comment_id < 1:
raise Http404('Not found comment')
このような例外が発生した際には、例外に応じたエラーのページが表示されるよう Django フレームワークがレスポンスを返却するようになっています。上記の場合は Http404
という例外を発生させているため、レスポンスのステータスコードは 404
となります。また、上記はコメントの例になりますが、ユーザーに関しても同様です。
このように、ビュー等での処理中に問題があった場合には例外を発生させてそれをユーザーに伝えることも重要になります。もちろん、問題があることを伝える文章や HTML を HttpResponse
のボディに設定して返却するのでも良いです。ダメなのは、問題があるからといってレスポンスの返却も例外の発生も行わないことです。
また、urls.py
で URL のマッピングを行なっていない URL に対してリクエストが送信された際は下の図のようなエラーページが表示されることになります。この場合は、ビューの関数が実行されることなく、Django フレームワーク側でレスポンスが自動的に生成されて返却されることになります。
以上で、特に今回実装したビューに関する動作確認は完了となります。
リストや各インスタンスの内容が表示されるだけなので、とても「掲示板アプリ」にも見えないかもしれないですが、後々の説明の中でコメントの投稿などもできるようになり、少しずつ掲示板としてのアプリに近づいていくことになりますので少々我慢していただければと思います。
また、現状、ユーザーとコメントが完全に独立していますが、これらはリレーションによって互いに関連付けられ、ユーザーはコメントの投稿者として扱うこともできるようになります。また、これに関しては実例を示す予定はないですが、リレーションを利用することでコメントとコメントを関連付け、コメントに対する返信なども行えるようにすることも可能です。このリレーションに関しても後ほどの連載の中で説明しますが、それまではユーザーとコメントは独立して扱うことになりますので、これに関しても了承していただけると幸いです。
今回はウェブブラウザからの操作によってビューの関数が実行される様子を確認しただけですが、このビューの関数が実行されるようになっただけでもウェブアプリ開発においては大きな一歩を前進できたと考えて良いと思います。
極端な話をすれば、ビューの関数が実行されるようになれば、あとはビューの関数を作り込むことで自身の好きなウェブアプリを開発可能です。ただ、効率的に開発をするためには、テンプレートやモデルなども利用したほうが良いので、この辺りを次の連載以降で是非理解していただければと思います!
スポンサーリンク
まとめ
このページでは、Django におけるビューについて解説を行いました!また、ビューと関係の深い URL マッピングについても解説しています。
Django におけるビューはウェブアプリの窓口的存在です。自身で開発を行うプロジェクト内において、Django フレームワークからまず実行される関数はビューとなります。ビューはリクエストを受け取り、レスポンスの返却 or 例外の発生を行う必要がある点や、リクエストに応じた処理・レスポンスの返却を行う必要がある点がポイントとなると思います。
また、ビューの関数が Django フレームワークから実行されるようにするためには、urls.py
での URL のマッピングも必要となります。
極端な話、ビューだけでもウェブアプリは作ることができてしまうのですが、それではメンテナンス性の悪いアプリとなってしまうため、適切にテンプレートやモデルを利用するほうが良いです。
その1つであるテンプレートについては次の連載の下記ページで解説していますので、是非次のページも読んでみてください!
