伊達要一@とうきょうDD954の書棚と雑記

伊達要一の読んだ本の紹介と書評、それと雑記

【Python/Django】「はじめての Django アプリ作成、その 1」の逐次解説(1)

f:id:yohichidate:20170608155451p:plain
一通り写経をやって慣れてきたので、今度は公式のドキュメントに挑戦してみます。といってもチュートリアルですが。逐次解説的なものをやっていきたいと思います。
はじめての Django アプリ作成、その 1 | Django documentation | Django
Django のドキュメントは、未翻訳の箇所がチラホラあったりするので、そういうところを補う意味でもやっていこうかと。

このチュートリアルでは簡単な投票アプリ(poll)を作成するようです。

Poll アプリケーションは 2 つの部分からなります:

  • ユーザが投票したり結果を表示したりできる公開用サイト
  • 投票項目の追加、変更、削除を行うための管理 (admin) サイト
はじめての Django アプリ作成、その 1 | Django documentation | Django

前者は基本的にソースをシコシコ書いていくもの、後者は Django の標準的な機能として持っている部分になる。

Django は既にインストール済み として説明を進めます。

はじめての Django アプリ作成、その 1 | Django documentation | Django

Python の開発環境やDjango のインストールに関してはこちらの記事を参照のこと。
yohichidate.hatenablog.com
yohichidate.hatenablog.com
インストールされているバージョンを確認するにはこちらのコマンドをCLI上で実行すればOK。

python -m django --version

現時点で導入されている Django のバージョンが「2.0.1」のように表示される。

This tutorial is written for Django 2.0, which supports Python 3.4 and later. If the Django version doesn't match, you can refer to the tutorial for your version of Django by using the version switcher at the bottom right corner of this page, or update Django to the newest version. If you're using an older version of Python, check どのバージョンの Python でどのバージョンの Django が使えますか? to find a compatible version of Django.

はじめての Django アプリ作成、その 1 | Django documentation | Django

(私訳)
このチュートリアルDjango 2.0 向けに書かれています(Django 2.0 は Python 3.4以降をサポートしています)。
もし Django のバージョンが 2.0 と異なる場合、チュートリアルページの右下にある「バージョンスイッチャー」(「Documentation version: 2.0」となっているボタン)を使用して、使用しているバージョンの Django チュートリアルを参照するか、または Django を最新のバージョンにアップデートしてください。
もし古いバージョンの Python を使っている場合、「どんなバージョンのPythonでどのバージョンのDjangoが使えますか?」をチェックして、対応しているバージョンの Django を探してください。
(補足)
基本的には先に述べたインストール方法を用いて仮想環境を立てて、そこでやればそこまでややこしくない。というか、Ubuntuとかだと、標準で入っているPythonが2.xx系だったりして、そこに依存するものがあると非常に面倒なことになるので、基本的にはPythonDjangoで何かを作ってみるときには仮想環境に分離した方が面倒が少なくて済む。
遠くない未来、標準でインストールされるPythonも3.xx系になるだろうけど、それまでは pyenv や virtualenv を活用した方が良い*1

一方で、Windows 環境でやる場合にはあまり悩まず Python3.xx 系を入れて*2、venv を使っても良いのかも知れない。


プロジェクトを作成する

初めて Django を使うのなら、最初のセットアップを行う必要があります。通常は、 Django の プロジェクト (project) を構成するコードを自動生成します。プロジェクトとは、データベースの設定や Django 固有のオプション、アプリケーション固有の設定などといった、個々の Django インスタンスの設定を集めたものです。

はじめての Django アプリ作成、その 1 | Django documentation | Django

要するに、Django を使ったアプリケーションの素材を展開してくれるもの程度に思っておけば良い。
先に述べた方法で仮想環境を仕込み済みのディレクトリへ移動して、以下のコマンドを実行する。

# django-damin startproject projectname
# 例
django-admin startproject mysite

例で挙げたコマンドの場合、実行したディレクトリ上に「mysite」ディレクトリが作成されて、その中に Django で使うような道具だてが準備されている。

注釈


プロジェクトの名前を付けるとき、組み込みの Python モジュールや Djangoコンポーネントの名前を使わないようにしてください。とりわけ、 django (Django 自体と名前が衝突します) や test (組み込みの Python パッケージ名と名前が衝突します) を使わないようにしましょう。

はじめての Django アプリ作成、その 1 | Django documentation | Django

上のコマンドにおける projectname (例の場合は「mysite」)については勿論任意の名称で構わない。
が、チュートリアルにあるように、 PythonDjango で使っている名前を用いると、トラブルが起きる。多くのチュートリアルにおいて「mysite」が使われているのは、これが理由。公式で使っている以上、ほぼ間違いなくかぶらないことがわかっているから。
実際にアプリケーションを作る際には、そのあたりに注意が必要。

コードはどこに置くの?


(モダンなフレームワークを使わない) 古いプレーンな PHP の経験があるなら、これまでは Web サーバのドキュメントルート下 (/var/www といった場所) にコードを配置してきたことでしょう。 Django ではそうしないでください。 Python コードを Web サーバーのドキュメントルート下に置かないでください。コードをドキュメントルート下に置くと、 誰かがコードを Web を介して読めるようになってしまうからです。これは安全上良くありません。


コードはドキュメントルートの外、例えば /home/mycode の ような場所に置きましょう。

はじめての Django アプリ作成、その 1 | Django documentation | Django

後ほど解説されるであろう仕組みによって、 Web 経由でアクセスするとドキュメントルートの外にあっても適切に振り分けてくれる。従って Webサーバのドキュメントルート上に置く必要もなく、置いてはいけないということになる。
ただ、手元のマシン上でお勉強的に作って動かす場合、大概 /home/username/ 配下のどこかに置くことが殆どだし、そもそも外に対して公開しないため、今の時点ではそこまで気にする必要はない。インターネットやイントラネット上に公開されているサーバに置いて動かすときに気をつければ良い話ではある。


startproject は projectname として記述した名称のディレクトリを作成して、その配下に以下のファイル・ディレクトリを生成する。

mysite/
  ├ manage.py
  └ mysite/
     ├ __init__.py
     ├ settings.py
     ├ urls.py
     └ wsgi.py

それぞれの役割について、逐次記述する。

外側の mysite/ ルートディレクトリは、このプロジェクトのただの入れ物です。 この名前は Django に関係しませんので、好きな名前に変更できます。

はじめての Django アプリ作成、その 1 | Django documentation | Django

そもそも論として、ここのディレクトリは先述の「startproject」のところで任意の名称にしているため、その必要もないと思われる。技術的に変更しても問題無いということ。

manage.py: Django プロジェクトに対する様々な操作を行うためのコマンドラインユーティリティです。詳しくは django-admin と manage.py 内の manage.py を参照してください。

はじめての Django アプリ作成、その 1 | Django documentation | Django

manage.py は、「startproject」のところで使った django-admin と同様に Django において管理者権限の処理を行うためのコマンドラインユーティリティ。django-admin と異なる点は、

  1. Django プロジェクト毎に自動的に作成される
  2. プロジェクトのパッケージを sys.path に保持する
  3. プロジェクトの settings.py ファイルを指定するように DJANGO_SETTINGS_MODULE 環境変数を設定する

の3点。通常はプロジェクト内で作業をするときには、 manage.py を使うことになる。

内側の mysite/ ディレクトリは、このプロジェクトの実際の Python パッケージです。この名前が Python パッケージの名前であり、 import の際に 使用する名前です (例えば import mysite.urls) 。

はじめての Django アプリ作成、その 1 | Django documentation | Django

外側の mysite/ ルートディレクトリと違って、こちらは Python/Django で実装するときに使うディレクトリ。ディレクトリ名を変えたりすると動かなくなる。実は manage.pyDJANGO_SETTINGS_MODULE 環境変数に指定しているのは、このディレクトリ配下の settings.py になる(詳しくは後述)。
manage.py のところで「プロジェクトのパッケージを sys.path に保持する」とあるように、実行したディレクトリに対して path を通してくれるので、上述のような「import mysite.url」というような記法でインポートが出来る。

mysite/__init__.py: このディレクトリが Python パッケージであることを Python に知らせるための空のファイルです。Python の初心者は、 Python の公式 ドキュメントの more about packages を読んで下さい。

はじめての Django アプリ作成、その 1 | Django documentation | Django

Django 云々というよりも、Python の話になってくるのであまり詳しく立ち入りたくないところではあるけども、上記リンク先の日本語版から説明を引用。

パッケージ (package) は、Python のモジュール名前空間を "ドット付きモジュール名" を使って構造化する手段です。例えば、モジュール名 A.B は、 A というパッケージのサブモジュール B を表します。ちょうど、モジュールを利用すると、別々のモジュールの著者が互いのグローバル変数名について心配しなくても済むようになるのと同じように、ドット付きモジュール名を利用すると、 NumPy や Python Imaging Library のように複数モジュールからなるパッケージの著者が、互いのモジュール名について心配しなくても済むようになります。


(中略)


パッケージを import する際、 Python は sys.path 上のディレクトリを検索して、トップレベルのパッケージの入ったサブディレクトリを探します。


あるディレクトリを、パッケージが入ったディレクトリとしてPython に扱わせるには、ファイル __init__.py が必要です。このファイルを置かなければならないのは、 string のようなよくある名前のディレクトリにより、モジュール検索パスの後の方で見つかる正しいモジュールが意図せず隠蔽されてしまうのを防ぐためです。(後略)

6. モジュール (module) — Python 3.6.4 ドキュメント

長々と引用した感があるけども、要するに「パッケージが入ったディレクトリ」として Python に扱わせるのに必要なファイルと思えばOK。実物を開いてもらえば分かる通り、中身は空っぽ。なお、上記 Python のドキュメントにこの後記載されているけども、 パッケージのための初期化コードを実行したり、 __all__ 変数を設定してパッケージからインポートするモジュールを限定させることも可能。詳しくは上記リンクのドキュメントを参照のこと。

mysite/settings.py: Django プロジェクトの設定ファイルです。 設定の仕組みは Djangoの設定 を参照してください。

はじめての Django アプリ作成、その 1 | Django documentation | Django

manage.py のところで少し触れたけども、要するに設定ファイル。必要に応じて追記したり修正したりする。その内容については今後のチュートリアルで触れられる(はず)。
ちなみに、デフォルトの値は django/conf/global_settings.py で、以下のコマンドで現在の設定とデフォルトとの違いを確認することが可能。

python manage.py diffsettings

あと地味に重要なのがこちら。

セキュリティ
設定ファイルにはデータベースのパスワードのような重要な情報が入っているため、設定ファイルへのアクセスは出来るだけ制限してください。例えば、設定ファイルのパーミッションを、あなたとWebサーバだけが読み取りできるようにしてください。共有ホスティング環境で運用する場合、これは極めて重要な事項です。

Djangoの設定 | Django documentation | Django

自分の手元環境で遊ぶ分にはそこまで気にしなくても良いけども、テスト的にインターネットに繋がっているサーバに置いたりするときには気をつけましょう。
最後に参照先としてドキュメントの関連ページを貼っておきます。
Django ドキュメント>トピックガイド>Djangoの設定
Django ドキュメント>APIリファレンス>設定


mysite/urls.py: Django プロジェクトの URL 宣言、いうなれば Django サイトにおける「目次」に相当します。詳しくは URL ディスパッチャ を参照 してください。

はじめての Django アプリ作成、その 1 | Django documentation | Django

Django の便利なところでもあり、最初はわかりにくい部分でもあるのがこれ。引用にあるリンク先の説明もところどころ未翻訳だったりしてドキュメントだけを見て進めようとすると閉口するし、ウェブに転がっている解説記事が間違っているケースが多数あって詰まりやすいところ。
yohichidate.hatenablog.com
こちらの記述をもとに、ウェブからのリクエスト処理のフローを簡単に記述。

  1. ROOT_URLCONF に設定されているモジュールをルート URLconf として使う。通常は mysite/settings.pyROOT_URLCONF に記述されている値を用いる。大概 /mysite/urls.py にするが、例外もある。
    1. その例外が /mysite/settings.pyMIDDLEWARE で HttpRequest オブジェクトに urlconf という属性を設定した場合。とりあえずはそういうこともある程度で十分。
  2. /mysite/urls.py なり、他に指定したモジュールなりをロードして、 urlpatterns 変数を探す。urlpatterns 変数は、Pythondjango.urls.path()django.urls.re_path() インスタンスのリストでなければならない。
    1. 簡単に云うと、ここに URL に対応させたいモジュールの urls.py なり名前空間なりを書いていく。その際に上記リンクの記述方じゃないとダメという話。
  3. Djangourlpatterns 変数内の値を順に調べて、リクエスト URLに最初にマッチしたところで止まる。
  4. マッチした urlpatterns 変数内の値に記述された特定のビューをインポートして呼び出す。
    1. このビューは単純なPython関数かクラスベースのビューになる。
      1. 要するに、Pythonの関数を使って呼び出すか、クラスベースのビューを使って呼び出すかという話。単純なというのはムダな装飾だと思う(こなみかん)。
    2. 変数内の値に記述された特定のビューをインポートして呼び出す際に以下の引数を渡す。
      1. HttpRequestインスタンス
      2. 一致した URLパターン から「名前付きグループ」が返されなかった場合、「正規表現からの一致が位置引数として提供される」*3
      3. キーワード引数は「パス式に一致する任意の名前付き部分」や「 django.urls.path() または django.urls.re_path() へのオプションである kwargs引数によってオーバーライドされる」*4
  5. URL パターンが一致しない、またはこのプロセスの間の任意の時点で例外が発生した場合、 Django は 適切エラー処理ビューを呼び出します。リンク先の エラー処理 を参照してください。

クッソ長くなったけども、要するに普通のフローで言えば

  1. mysite/settings.pyROOT_URLCONF を読むよ。
  2. ROOT_URLCONF には mysite/urls.py がたいてい指定されているよ。
  3. mysite/urls.pyurlpatterns 変数にあるパターンを検索するよ
  4. マッチした先に引き渡すよ
  5. マッチしなかったらエラーハンドリングしてエラーを出すよ

ということになる。

mysite/wsgi.py: プロジェクトをサーブするためのWSGI互換Webサーバーとのエントリーポイントです。詳細は WSGI とともにデプロイするには を参照してください。

はじめての Django アプリ作成、その 1 | Django documentation | Django

そもそも WSGI って何? って話にまずなりますわな*5。こいつは Web Server Gateway Interface の略で、
Python のある意味目玉になるようなもので「Webサーバ と Webアプリケーション を接続するための標準化されたインタフェース定義」のこと。無茶苦茶単純化してしまえば「WSGI にさえ対応してあれば、どこのサーバに持っていってもアプリが動くよ」というお話。
当然といえば当然だけども DjangoWSGI に対応しているので、使うときに気にする程度で今は良いはず。

正直ここまで長くなるとは思わなかったので一旦ここで切りましょう。まだ殆ど手を動かしていないけども、これからガリガリ書いて行くはずなのでそのつもりで。

その他のナレッジについては以下を参照。
yohichidate.hatenablog.com

*1:モダンなやり方で言えば、Python3.3 以降に標準で導入されている venv を使った方が勿論良いのだろうけど、標準が2.xxになっている環境では非常に面倒ではある

*2:そもそも Windows には Python が標準で導入されていないので、既存のシステムに対する依存問題はあまり考えなくて良い

*3:TODO: Google 翻訳による機械翻訳。後日見直し予定。原文「If the matched URL pattern returned no named groups, then the matches from the regular expression are provided as positional arguments.」

*4:TODO: Google 翻訳による機械翻訳を元に多少修正。後日見直し予定。原文「The keyword arguments are made up of any named parts matched by the path expression, overridden by any arguments specified in the optional kwargs argument to django.urls.path() or django.urls.re_path().」

*5:Python にクッソ詳しいけど、Django は初めてみたいなひとはともかく。そんなひとはこんなチュートリアルくらい鼻歌交じりで流すだろうし