Django-Tutorial-pollsアプリケーション

概要

Djangoドキュメントのチュートリアルに従って、mysiteプロジェクトを作成し、その中にpollsアプリケーションを作成する。

プロジェクトの作成

プロジェクトの作成django-adminで実行する。チュートリアルのプロジェクト構成ではmysiteディレクトリーの下にmysiteサブディレクトリーとしているが、ここではmysite/configという構成にした。

ディレクトリー構成は以下のようになっている。

settings.pyを以下のように編集する(初期設定の詳細はこちら)。

  • ローカルサーバーでの開発のため、ALLOWED_HOSTS'localhost'を設定
  • DATABASESはMySQL用に設定
  • その他、言語コードやタイムゾーンの設定

開発用サーバーを起動して、"Congratulations!"の画面を確認。

pollsアプリケーションの作成

startappコマンドでpollsアプリケーションを作成。

manage.pyは実行可能ファイルなので、以下でも作成できる。

pollsアプリケーション作成後の構成は以下の通り。

view関数の定義

view関数はMTVの構成要素の一つで、URLからルーティングされ、モデルのデータ操作やブラウザー表示のための様々な処理を実装するもの。MVCモデルのコントローラーに相当する。

一般的にはview関数の戻り値にはブラウザー表示のためのテンプレートを渡すが、ここでは最も単純に、単に文字列だけを返すようにする。

  • HttpResponseモジュールをインポート
  • view関数index()を定義
  • HttpResponseのコンストラクターの引数に文字列を渡し、そのインスタンスを戻り値とする

URL conf~ルーティング

URLからview関数index()へのルーティングを設定する。pollsアプリケーションのビューなのでpolls/urls.pyで定義する。アプリケーションのurls.pyはデフォルトでは作成されないので、新たに作成して次の内容とする。

pollsアプリケーションのurlsモジュールをプロジェクトに認識させるため、conf/urls.pyに記述を追加する。

  • django.urlsパッケージのincludeモジュールを追加でインポート
  • path関数でアプリケーションのurls関数をインポートし、アプリケーションのURLに紐づけ

確認

サーバーが起動した状態で、サブディレクトリーpolls/にアクセスする。今の構成ではlocalhost:8000/polls

ブラウザーの画面には、以下のテキストが表示される。

 

 

Django – Tutorial – admin

概要

Djangoのチュートリアル、管理者ページの部分を整理。

管理者ログインページ

Djangoのデフォルトの状態で、既に管理者の環境が準備されている。サーバーを起動してadmin/サブディレクトリーでアクセスすると、以下のような管理者ログイン画面が表示される。

管理者の作成

createsuperuserコマンドで管理者を作成する。

管理者のユーザー名、メールアドレス、パスワードを登録し、管理者アカウント作成。プロンプトの一部が日本語になっている。

パスワードを'admin'という文字列を含むかなり簡単なものにしたため「ユーザー名と似すぎています」という警告が出たが、ここはyesにしておいた。

管理者ログイン・インデックスページ表示

作成した管理者アカウントでログインすると管理者インデックスページへ。この段階では、pollsアプリケーションが管理者で操作できるようにはなっていない。

管理者へのアプリケーションの登録

管理者がpollsアプリケーションを操作できるようにするために、polls/admin.pyに記述を追加する。

  • Qustionモデルのインポート
  • adminサイトにQuestionモデルを登録

admin.pypollsパッケージ内にあるのでfrom .models ...としているが、from polls.models ...でもよい。

インデックスページを再表示させると、今度はQuestionsが見られるようになった。

データの内容表示

インデックスページのQustionsをクリックすると、登録済みデータが表示される。What’s up?と表示されているのは、models.pyQuestionクラスで__str__メソッドを定義したおかげで、デフォルトの状態だとQuestion object (1)と表示される。

What’s upをクリックすると、フィールド内容の編集画面に移る。

フィールド名のQustion textDate publishedは、models.pyQuestionクラスで定義したフィールド名になっている。

  • Question textは、クラス定義のプロパティーquestion_textのアンダースコアがスペースに、先頭が大文字に変換されたもの
  • Date publishedDateTimeFieldの引数に指定した'date published'の先頭が大文字に変換されたもの

たとえば上記の3行目をDateTimeField()とすると、画面表示は元のプロパティー名に即してPub dateとなる。

データの編集

Qustion textDate publishedの内容を変更して「保存して編集を続ける」ボタンを押すと、変更した内容が反映される。

もちろんデータベース上でも変更されている。

変更履歴

画面右上の「履歴」ボタンを押すと変更履歴画面に移り、Question textDate publishedが変更された履歴が表示される。

 

Django Tutorial – Pythonシェル

概要

Pythonシェルの環境下でモデル操作をしてみる。Pythonドキュメントのチュートリアルの流れに沿っている。Laravelのtinkerでの操作と似ている。

シェルの起動・終了

シェルの起動はmanage.pyshellコマンド。終了はexit()

モデルの操作

準備・確認

モデル操作の開始時にモデルのインポートが必要。

from アプリケーション.models import モデルクラス

タイムゾーン表示のためにtimezoneオブジェクトをインポート。

timezone.now()で現在時刻を表示してみる。内部的にはUTCで扱われているので、その時点の日本時間とは9時間ずれている。

モデルの全データの取得。まだデータは登録されていない。

データの作成・保存・編集

作成

Questionモデルのコンストラクターでデータを作成。この段階ではメモリー上に作成されただけで、データベースには保存されていない。

pprintvarsでデータの内容を確認してみる。

各フィールドを見てみる。まだデータベースに登録されていないので、idは空になっている。

保存

save()メソッドでデータベースに保存。

MySQLでテーブルへの保存を確認。

データベースに保存されたのでidがセットされた。

編集

データのquestion_textの内容を書き替えてデータベースに保存。

データベースを確認して内容が変更されていることを確認。

データの取得

Managerオブジェクト

個別のモデルごとにManagerクラスのインスタンスが生成され、モデルのobjectsメンバーとして準備される。データの取得やフィルタリングなど操作は、このインスタンスのメソッドによって行われる。

モデル.objects

all()による全データの読み込み

all()メソッドによってテーブルに登録された全データを読み込める。

モデルクラス.objects.all()

Qustionには1つだけデータが登録されている。

__str__の定義

データ表示が殺風景なオブジェクトの表示になっているが、これを変更してquestion_textchoice_textを表示させるようにする。具体的には各モデルに__str__メソッドを定義する。

これでデータ内容の表示がわかりやすくなった。

get()による1つのデータの抽出

get()メソッドで条件を指定してデータを1つ取り出せる。

モデルクラス.objects.get(条件)

id1のデータを取り出す。

該当するデータがない場合はModel.DoesNotExist例外、複数のデータが存在する場合はModelMultipuleObjectsReturned例外。以下はDoesNotExistの例。

主キー(primary key)を指定してでも取り出せる。Djangoではprimary keyのショートカットとしてpkが準備されている。

フィルターによる抽出

filter()メソッドでデータを抽出できる

モデルクラス.objects.filter(条件)

以下はid=1の条件で抽出した結果で、今回の例の場合はデータを1つ含むQuerySetが得られる。

存在しないidで抽出すると空のQuerySetが得られる。

文字列の前方一致の抽出例。引数のフィールドにアンダースコアを2つ(‘__‘)連ねて様々な条件を指定できる。フィルターの条件の書き方はこちらに整理した。

フィールド__条件=値

ここではフィールド__startswith='文字列'として、フィールドが指定した文字列で始まるデータを抽出している。

登録の年が同じデータを抽出する例。まず現在日時の年を取り出して変数current_yearにセットして、pub_dateの年がこれに等しいデータをフィルタリング。datetime型のフィールドの年の条件でフィルタリングするにはフィールド名__year=年とする。__yearのアンダースコアは2つ。

リレーションがあるモデル

親データに属する子データ群

親データに属する(これを参照している)データのManagerオブジェクトを取り出すには以下のように書く。

親データ.小文字の子モデル名_set

たとえば変数qが Questionモデルのid=1のデータを指している状態で、これに属するChoiceデータ群の全てを取り出すと以下のようになる。まだChoiceデータを1つも登録していないので結果は空。

親データに属する子データの作成

親データに関連付けられた子データを新たに作成するときは以下のように書く。

親データ.小文字の子モデル名_set.create(...)

qに関連付けられたChoiceデータを3つ登録。

MySQLでテーブルの内容を確認すると、Questionテーブルのid=1のデータを参照する3つのデータが登録されている。

<閑話休題>
“What’s up?”はくだけた言い方の挨拶で「調子はどう?」、「何か(変わりは)あったかい?」といった感じ。”Not much.”は「普通だよ」とか「特にないね」といった常套句のようだ。”The sky.”はupにひっかけて「(上は)空さ」というジョーク表現(無理やり日本語字幕にするなら「何かあったかい?」「暖かいね」とかなどと考えたが単なる駄洒落か・・・)。”Just hacking again.”はよくわからなかった。

子データのall/count/filter

登録されたデータをallメソッドで取り出してみる。

データの個数はcountメソッドで。

子データ群のフィルタリングは通常と同じように指定。

親データの条件によるフィルタリング

親データの条件でフィルタリングする場合、filter()の中で小文字の親モデル名を使うが、直接以下のように書くとエラーになる。

filter(小文字の親モデル名_フィールド__条件)→エラー

以下の例では、Choiceの親データquestionquestion_textフィールドの条件でフィルタリング仕様としてエラーになっている。

 

親データのフィールドの条件の場合、親データとフィールドの間のアンダーラインを2つにする。

親データ.子データ_set.filter(親データ__フィールド__条件)

たとえばQuestionChoiceの場合は以下のようになる。

q.choice_set.filter(question__フィールド__条件)

以下はテキストが'What'で始まる親データに属する子データを抽出している。

以下は登録年が今年の親データに属する子データを抽出している。

データの削除

まずテキストに'huck'(大文字小文字を問わない)を含むchoiceデータをデータベースから得る。

そのデータをdeleteメソッドでデータベースから削除。

モデル.delete()

MySQLで削除されていることを確認。

 

Django – filterの条件

一致

Case Sensitive

 BINARY field=値
field=BINARY 値
field=値
field__exact=値

Case Insensitive

field=値 field__iexact=値

大小比較

field>値 field__gt=値
field>=値 field__gte=値
field<値 field__lt=値
field<=値 field__lte=値

部分一致~LIKE

Case Sensitive

field LIKE BINARY 'text%' field__startswith='text'
field LIKE BINARY '%text' field__endswith='text'
field LIKE BINARY '%text%' field__contains='text'

Case Insensitive

field LIKE 'text%' field__istartswith='text'
field LIKE '%text' field__iendswith='text'
field LIKE '%text%' field__icontains='text'

何れかに一致~IN

field IN (...) field__in=[...]

範囲~BETWEEN

field BETWEEN min AND max field__range=[min, max]

日付の年・月・日の一致

DATE_FORMAT(date, '%Y') = 'year' date__year=year
DATE_FORMAT(date, '%m') = 'month' date__month=month
DATE_FORMAT(date, '%d') = 'day' date__day=day

NULLとの比較

field IS NULL field__isnull=True
field IS NOT NULL field__isnull=False

 

Django – django-adminとmanage.pyの基本コマンド

実行方法

manage.py

プロジェクトルート直下、manage.pyファイルのある場所で実行

コマンド

作成・起動

startproject
$ django-admin startproject プロジェクト名

  • プロジェクト作成
startapp
$ ./manage.py startapp アプリケーション名

  • アプリケーション作成
runserver
$ ./manage.py runserver [IPアドレス[:ポート]]

  • 開発用サーバーの起動

シェル

shell
$ ./manage.py shell

  • Pythonシェル起動
dbshell
$ ./manage.py dbshell

  • settings.pyDATABASESで設定したDBMSのシェル起動

チェック・確認

check
$ ./manage.py check

  • プロジェクトの不具合有無のチェック
dumpdata
$ ./manage.py dumpdata

  • データベースの内容をダンプ
inspectdb
$ ./manage.py inspectdb

  • モデルクラスの内容を表示

マイグレーション

makemigrations
$ ./manage.py makemigrations

  • models.pyに基づくマイグレーションファイルの作成
showmigrations
$ ./manage.py showmigrations

  • マイグレーションファイル・状態の表示
migrate
$ ./manage.py migrate

  • マイグレーション実行
migrate~ロールバック
$ ./manage.py migrate アプリケーション名 マイグレーション名

  • アプリケーションのマイグレーションが実行済みのときは手前までロールバック
  • 未実行の時はマイグレーション

その他

$ ./manage.py makemessages

$ ./manage.py compilemessages

$ ./manage.py createsuperuser

$ ./manage.py changepassword

・・・

 

Django – マイグレーションのテーブル名指定

概要

Djangoのマイグレーションでテーブルを生成すると、テーブル名は、アプリケーション名とスネークケース化されたモデル名がアンダースコアで繋がれた名前になる。

たとえばアプリケーション名がmy_app、モデル名がMyModelのときのテーブル名はmy_app_mymodelとなる(モデル・テーブル等の名前)。

これが次のような点で気持ち悪い。

  • 単数形のモデル名のままでテーブル名も単数形になる
  • モデル名がスネークケースにならず区切りがなくなる

この自動で付与されるテーブル名を変更する方法があることを知った(参考サイト:Django モデルのメタクラス)。

クラス定義にclass Metaを加える

アプリケーションとモデルを以下の設定とする。

アプリケーション名 warehouse
モデルクラス名 StockItemShippingOrder

これでマイグレーションを実行すると、テーブル名はwarehouse_stockitemwarehose_shippingorderのようになる。これをstock_itemsshipping_ordersのように変更したい場合、クラス定義に以下のように追記する。

マイグレーションを実行。

テーブル確認。

 

Django – モデル・テーブル等の名前

目的

Djangoでアプリケーションとモデルを作成し、マイグレーションした場合の、テーブル名、フィールド名などを確認。アプリケーション名をmy_app、モデルクラス名をMyModel1MyModel2とする。

なお、自動付与されるテーブル名は変更することが可能

手順

アプリケーション作成

アプリケーション名はスネークケース(my_app)

アプリケーション構成クラス名の確認

アプリケーション名がスネークケースの場合、アプリケーション構成クラス名はアッパーキャメルケースになり、Configが付加される。

my_app → MyAppConfig

アプリケーション登録

settings.pyINSTALL_APPSにアプリケーション構成クラスを追加。ここではアプリケーション構成クラスを追加している。

モデル定義

my_apps/models.pyファイルで2つのモデルクラスMyModel1MyModel2を定義。MyModel2にはMyModel1への参照キーを設定する。

マイグレーションファイル作成

マイグレーション

マイグレーションを実行してテーブルを生成させる。

テーブル確認

テーブル名は’アプリケーション名_小文字化されたモデル名‘となる。キャメルケースのモデル名をスネークケースにはしてくれない。

my_app + MyModel1 → my_app_mymodel1
my_app + MyModel2 → my_app_mymodel2

テーブル構造を確認。

MyModel2の外部キーは、’参照先モデル名(スネークケース)_id‘となる。この場合は参照先がMyModel1なので、

MyModel1 → my_model1_id

まとめ

これを表で整理すると以下のようになる。

my_app
アプリケーション構成クラス名(生成) MyAppConfig
モデルクラス名(定義) MyModel1 MyModel2
テーブル名(マイグレーション) my_app_mymodel1 my_app_mymodel2
外部キー名(マイグレーション) my_model1_id

これを何とか図にすると、以下のようになる。

まとめると以下のようになる。

  • アプリケーション名:スネークケース
    →アプリケーション構成クラス名:アッパーキャメルケース
  • モデルクラス名:アッパーキャメルケース
  • テーブル名:アプリケーション名_小文字化されたアプリケーション構成クラス名
  • 外部キー名:参照先のモデル名(スネークケース)_id

 

Django – settings.py – INSTALLED_APPS

 

概要

settings.pyINSTALLED_APPS配列でアプリケーションを登録する。

Django – settings.pyへ。

デフォルトの内容

プロジェクト作成直後のsettings.pyにおけるINSTALLED_APPSの内容は以下の通り。コメントはこちらで追記。

アプリケーションの登録

アプリケーション登録のためには、アプリケーション構成クラスを登録するが、書き方には2通りある。登録するアプリケーションをmy_appとすると、以下の通り。

  1. 'my_app.apps.MyAppConfig',
  2. 'my_app',

1の書き方は、明示的にアプリケーション構成クラスを書く方法。

manage.pyでアプリケーションを作成するとmy_appディレクトリ下にapps.pyファイルが作成され、アプリケーション構成クラスが定義される。

アプリケーション構成クラス(MyAppConfig)はAppConfigを継承している。またアプリケーション名のスネークケースがクラス名ではアッパーキャメルケースになり、Configが付加されている(モデル・テーブル等の名前を参照)。

2の書き方は、アプリケーションパッケージ名を書く方法。

この場合Djangoはmy_appパッケージのmy_app/__init__.py内のdefault_app_config変数で設定されたアプリケーション構成クラスを使う。

  • デフォルト状態で__init__.pyが空の場合、AppConfigクラスが使われる
  • __init__.pydefault_app_config='my_app.apps.MyAppConfig'が設定されていれば、apps.py内のMyAppConfigが使われる

参考サイト:Django アプリケーションの登録

 

Django – migration – 初期状態

概要

プロジェクト作成直後のマイグレーションを記録。

初期状態

プロジェクト作成直後のマイグレーションの状態は以下のとおりで、INSTALLED_APPSで設定されたアプリケーションに対応したマイグレーションファイルが準備されている。

マイグレーション実行

初期状態でマイグレーションを実行。

作成されるテーブル

マイグレーションの状態

初期状態で確認したマイグレーションが実行されている。

 

Django Tutorial – モデルの作成とマイグレーション

概要

Djangoのモデル作成について、チュートリアルに沿って進めた内容の整理。mysiteプロジェクトのpollアプリケーションのモデルを作成する手順。

前提

  • mysiteプロジェクト作成・初期設定済み
  • pollsアプリケーション作成済み

手順

  • models.pyを編集し、モデルクラスを記述
    • models.pyはアプリケーションディレクトリー下
    • モデルクラスの内容=テーブルのフィールド構成
  • settings.pyINSTALLED_APPSにアプリケーション登録
    • アプリケーション構成クラスを追加
  • manage.py makemigrationsコマンドでマイグレーションファイルの準備
    • 必要ならmanage.py sqlmigrateでSQLを確認
  • マイグレーション実行

models.pyの編集

モデルはデータベースの操作をラップし、DBMSによる差異を吸収する。

  • Djangoでは、モデルはアプリケーションごとに作成する
  • モデルの構造はPythonのクラスとして記述する
  • モデルの記述場所はアプリケーションディレクトリー下のmodels.py

以下のツリーでmodels.pyの場所を確認しておく。

アプリケーション作成直後のmodels.pyファイルの内容は以下のとおり。モデルが継承するmodelsパッケージをインポートしている。

QustionモデルとChoiceモデルを作成するため、models.pyを以下のように編集。

要点は以下のとおり。

  • モデル名は単数形でQustionChoiceの2つ
  • 各モデルはdjango.db.models.Modelクラスを継承
  • 各モデルクラスのフィールドはmodelsパッケージのField関係クラスのインスタンス
    • たとえばCharFieldは文字列フィールド、DateTimeFielddatetime型のフィールドなど
  • こちらで定義したquestion_textpub_dateなどのフィールド名はPythonのコードで扱われるとともに、データベースのフィールド名としても使われる
  • Fieldコンストラクターの第1引数では、より人が読みやすいフィールド名を付けることができる
    • 上の例では'date published'
  • Fieldによっては必須の引数があり、たとえばCharFieldmax_lengthは必須であり、データベースフィールド定義のほか、バリデーションにも使われる
  • ForeignKeyは外部キーであり、Choiceモデルのquestionフィールドは1つのQuestionモデルを参照する
    • また参照元の削除に伴って削除される設定もされている

なお、自動作成されるテーブル名を変更したい場合はここを参照

アプリケーションの追加

pollsアプリケーションを作成してモデルを定義したが、これらはまだDjangoのプロジェクトには認識されていない。プロジェクトとしてモデルとデータベースを結びつけるマイグレーションのためには、アプリケーションをプロジェクトに登録する必要がある。

アプリケーション登録のために、settings.pyINSTALLED_APPSに記述を加える。ここではアプリケーション構成クラスを追加する。

ここではpollsアプリケーションのPollsConfigクラスを登録している。このクラスはアプリケーション作成時にDjangoにより生成、アプリケーションのapps.pyファイルで定義されていて、AppConfigクラスを継承している。

pollsアプリケーションの場合はpolls.apps.PollsConfigとして参照される。

マイグレーションファイル作成

マイグレーションファイルの作成は以下のコマンドで実行。

以下はpollsアプリケーションの実行結果で、アプリケーションのmigrationsディレクトリーにマイグレーションファイル(0001_initial.py)が作成され、マイグレーションによりQuestionChoiceの2つのモデルが作成されることが表示されている。

0001_initial.pyファイルの内容を見てみる。

2つのモデルとも、クラス定義にはなかったidフィールドが追加されている。これらのフィールドはAUTO_INCREMENTタイプで自動的に作成され、主キー(primary_key)として設定されている。

SQLの確認

マイグレーションファイルの内容でデータベースのテーブルを作成する際のSQLも確認することができる。

以下はpollsアプリケーションのマイグレーションファイルをSQLで確認した結果。

読み易いように整形した結果。

MySQLの場合、

  • 自動的に作成されたidAUTO_INCREMENTPRIMARY KEYが設定されている
  • CharField(max_length=200)varchar(200)となっている
  • datetime(6)の引数6は秒未満の小数部の桁数
  • モデルクラスではChoice.questionQuestionを参照するよう定義したが、SQLではpolls_choiceテーブルのquestion_idpolls_questionテーブルのidを参照するという風に、IDを介して参照している

マイグレーション実行

生成されたマイグレーションファイルに基づいて、以下のコマンドでマイグレーションを実行。

以下は今回の例で実行した結果。

manage.py showmigrationsで、pollsアプリケーションのマイグレーションファイルが実行されているのが確認できる。

MySQL側でテーブルを確認。2つのテーブルpolls_questionpolls_choiceが作成されている。

2つのテーブルの定義を確認。