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つのテーブルの定義を確認。

 

Django – マイグレーション操作

 

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

アプリケーションを作成・登録して、model.pyにモデルクラスを記述した後に実行。再実行の際は一度マイグレーションファイルを消した方がよい模様。

状態確認

マイグレーションの状態

マイグレーション実行のSQL表示

マイグレーション

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

指定したアプリケーションとマイグレーションが既にマイグレーション済みの場合はロールバックになる点に注意。

ロールバック

指定したマイグレーションの手前まで

0001_initialも含めて全て

マイグレーションファイル削除

migrationsディレクトリー下のマイグレーションファイルとキャッシュを削除。

 

Django – settings.py – TEMPLATES

概要

settings.pyTEMPLATESは配列・辞書の入れ子になっている。

'DIRS'
プロジェクトルート直下のテンプレートディレクトリーを指定する。そのサブディレクトリーも探索される。
'APP_DIRS'
アプリケーションディレクトリー下のテンプレートディレクトリー探索を有効にする。そのサブディレクトリーも探索される。

Django – settings.pyへ。

テンプレートの探索場所の詳細についてはこちら

初期状態

settings.py生成直後のTEMPLATESの内容は以下のとおり。

 

'DIRS': []と設定されていて、プロジェクトルート(この場合はprojectroot/)直下は探索されない。

'APP_DIRS': Trueと設定されていて、各アプリケーションディレクトリー下のtemplatesディレクトリーが探索される。

DIRS

プロジェクトルート直下のテンプレートディレクトリーを指定する。たとえば以下のようにtemplatesディレクトリーを準備した場合。

準備したtemplatesを探索させるためには、以下のように設定する。

あるいは以下のようにベースディレクトリーからのパスであることを明示する。この場合settings.pyimport osが必要。

ディレクトリーの指定はサブディレクトリーでもよい。たとえばconfigディレクトリー下のtemplatesディレクトリーとしたければ以下のように記述。

APP_DIRS

APP_DIR=Trueとすると、各アプリケーションディレクトリー下のtemplatesディレクトリーが探索される。そのサブディレクトリーも探索される。