Django – Tutorial – テンプレート

概要

DjangoドキュメントのチュートリアルPart3中”Write views that actually do something“の冒頭でビュー関数でのモデル操作を実装した後、テンプレートファイルを使った表示を実装している。

テンプレートの基礎についてはこちらを参照。

テンプレートディレクトリー/ファイルの作成

テンプレートファイルの内容

pollsディレクトリー下にtemplatesディレクトリーを、その下にpollsディレクトリーを作成する。そのディレクトリー下に以下の内容でindex.htmlファイルを作成する。

これから、polls/viewsモジュールからこのテンプレートを参照するよう編集していく。

パスの書き方の注意点

テンプレートファイルのアンカータグは以下のように書かれている。

当初/polls/{{ ... }}の部分の先頭の'/'を抜かして書いてしまって、polls/{{ ... }}としたところ、URLが以下のようになってしまった。

http://localhost:8000/polls/polls/2/

現在のアプリケーションからの相対パスになってしまったためで、

http://localhost:8000/polls/ + /polls/2/

と解釈されてしまう。先頭のスラッシュを入れるとホスト名をルートとするパスとなる。ただしこの記事の最後の方にあるDTLのurlタグを使うと、このような心配をしなくて済むようになる。

テンプレートの探索

ディレクトリー・ファイル構成は以下の通り。

config/settings.pyで、以下のように設定している。

  • INSTALLED_APPS'polls.apps.PollsConfig'を登録
    pollsが探索に含まれる
  • TEMPLATES'APP_DIRS'Trueに設定
    polls/templatesが探索に含まれる

ので、polls/templatesとそのサブディレクトリー下がテンプレートファイルの探索場所に含まれる。

ビューにおけるレンダリング

loaderによる標準形

ビューの編集

テンプレートファイルを導入した場合の標準形は以下の構成になる。

  • django.templateパッケージのloaderオブジェクトをインポート
  • loader.get_template('テンプレートへのパス')でテンプレートを読み込み
  • テンプレートのrenderメソッドでレンダリングした結果を、HttpResponseに渡す
    render(context, request)

動作確認

http://localhost:8000/pollsにアクセスすると、2つのリンクが表示される。

 

このHTMLのソースコードは以下のようになっている。

それぞれのリンクをクリックしたときの遷移先URLとブラウザー表示は以下の通り。

  • href="/polls/2/"
    • http://localhost:8000/polls/2/
    • You’re looking at question 2.
  • href="/polls/1/"
    • http://localhost:8000/polls/1/
    • You’re looking at question 1.

renderショートカット

loaderを用いた標準形では、

  1. テンプレートのローダーによってテンプレートファイルを読み込み、
  2. これをレンダリングした結果をHttpResponseに渡す、

という2段階の処理となっている。Djangoにはこれを1行で済ませるrenderショートカットが準備されている。renderショートカットを使って、indexビューをより簡潔にしてみる。

1行目のHttpResponseのインポートはまだ手を入れていない他のビュー関数のためで、renderによる処理には必要ない。loaderのインポートも不要で、必要なのは3行目のrenderのインポートのみ。

14行目がrenderショートカットを導入した効果で、この1行でリクエスト、テンプレート、contextの指定を済ませてレスポンスを返している。

render(request, 'テンプレートパス', context)

404エラーの実装

存在しないidへの反応

indexテンプレートではQuestionの2つの要素が表示され、それぞれid=1, 2をリクエストパラメーターとして渡している(href="/polls/1/"など)。ところがQuestionに存在しないidを指定したURLでアクセスすると以下のようなエラーがブラウザーに表示される。

このエラーの代わりに、404エラーで反応させたい。

例外処理による標準形

ビューの編集

現在のdetailビューは以下のような内容。

存在しないインスタンスを指定すると例外が投げられるので、それをキャッチして404エラーをレイズするようにする。

テンプレートの準備

またrenderで指定しているdetailテンプレートを、polls/template/pollsディレクトリーに以下の内容で作成しておく。

実行結果の確認

これで存在しないidの値を指定したときのエラーは以下のように変化する。メッセージがHttp404クラスのコンストラクターに与えたテキストになっている。

get_object_or_404ショートカット

Djangoには、上のような複数行の例外処理を一行で書くget_object_or_404ショートカットが準備されている。

以下のようにget_object_or_404ショートカットをインポートすると、1行でQuestionデータを取得し、存在しなければ404エラーをレイズしてくれる。

存在しないidを指定したときのエラー表示は以下のようになる。エラーメッセージの内容は固定されていて変更できないようだ。

なおsettings.pyDEBUGFalseにすると、ブラウザー表示は以下の2行のより簡素な内容になる

テンプレートシステム

DTLによる記述

先ほどのindexテンプレートの内容は1行で変数を表示するだけの内容だったが、これをテンプレートらしくDTL~テンプレート言語を使って以下のように書き換える。

そうすると大きな見出しでQuestionデータのテキストが表示され、そのQuestionデータに関連付けられたChoiceデータのテキストが箇条書きで表示される。

 

今回のDTLでは、オブジェクトの属性を得るのにドット検索が行われている。通常のPythonの場合リストや辞書型のオブジェクトの要素は[]で参照されるが、DTLではこの記述方法が使えない。代わりにドットを使って以下の順序で探していく

  1. 辞書型のキー
  2. オブジェクトの属性
  3. リストのインデックス

今回の例では、辞書型のキーで取得できず、オブジェクトの属性として取得に成功する。

URLのハードコーディング回避

ハードコーディングの問題

現時点でindexテンプレートのアンカー要素のURLは"/polls/{{ question_id }}/"と書かれている。

 

この場合にリンクが張られるdetailのURLはurlsで定義されていて、たとえば以下の通り。

http://localhost/polls/1

ここでプロジェクト進行中に以下のように変更することとなったとする。

http://localhost/polls/specifics/1

この場合、indexテンプレートのアンカー要素の内容を全て以下のように変更する必要がある。

href="/polls/specifics/{{ question.id }}/"

さらにindexテンプレート以外でもこのルーティングを使っている場合、その分だけ変更が生じてしまう。

ハードコーディングの回避

urls.pyの確認

まずpolls/urls.pydetailビューへのルーティングにname='detail'で名前が付けられていることに留意。

ビューの変更

index/view.py中、アンカー要素のURL部分を以下のように変更する。

  • href="..."のURL部分を{% url %}に入れ替え
  • このタグの引数に、urlsnameで指定した名前とパラメーターを書く

一般化した書き方は以下の通り。このとき、先頭や末尾の'/'は不要。

{% url 'urlsのnameで定義した名前' クエリーパラメーター %}

HTMLの確認

生成されるHTMLは以下の通り。

URLの変更

URLの変更が必要な場合、1箇所だけ、urlsの内容を変更すればよい。

以下のように生成されるHTMLもすべて変更される。

そして以下のようにアクセスできるようになる。

URLの名前空間管理

名前空間管理の必要性

DTLのurlタグで、ルーティングに付けた名前を使って抽象化することができた。ところが、先の例の場合pollsアプリケーションのdetailと同じ名前を他のアプリケーションでも使う場合、見分けがつかない。

そこで、ルート名がどのアプリケーションのものか分かるようにする必要がある。

urls.pyの編集

urls.pyに以下の1行を追加する。

indexテンプレートの編集

次にindexテンプレートの名前指定部分を、以下のように'アプリケーション名:ルート名'に変更。

この場合の実行結果は変わらないが、他のアプリケーションでもdetailという名前のルーティングがある場合でも、pollsアプリケーションの同名のdetailが識別される。

urlsapp_nameが定義されている状態でurlタグでpolls:を書かないと以下のエラーになる。

 

Django – Tutorial – ビューでの処理

概要

DjangoドキュメントのチュートリアルPart3中”Write views that actually do something“では、それまで単に文字列だけを返してブラウザーに表示させていたビュー関数に、ビューでの処理を記述している。そこではデータベ ースのデータを使った処理を例にしている。

チュートリアルではこれに続いてテンプレートの扱い方を示しているが、ここではモデル操作の実装だけを取り出して整理する。

index関数の編集

チュートリアルで示されているindex関数の編集内容は以下の通り。polls.models.Questionをインポートしていることに注意。

http://localhost:8000/polls/にアクセスすると、questionsテーブルに登録されているデータが日時の新しい順に、カンマで区切られて表示される。

チュートリアルではデータが1つしか登録されていなくて分かりづらいので、もう一つデータを登録してみる。

コードの内容

モデルインスタンスのソートと抽出

Questionモデルの全てのインスタンスをpub_dateフィールドの降順に並べ替えて先頭から5個取出し、そのQuerySetインスタンスをlatest_question_listに参照させている。

  • モデル.objects.order_by()でモデルのデータをソートした結果をQuerySetとして返す
  • '-pub_date'で降順にソート/昇順の場合は'pub_date'
  • [:5]はコレクションのスライスで、先頭から5個のデータ(インデックスが5未満のデータ)を取り出す

シェルで実行してみると以下の通り。

引数を'pub_date'に変更すると並べ替え順序が昇順になり、古いデータから並べられたセットが得られる。

またスライスを[:1]にすると、インデックスが0の要素だけが得られる。

出力文字列の構成

latest_question_listの各要素を', 'をデリミターとして結合している。各要素はQuestionモデルのインスタンスだが、__str__メソッドが実装されているので、参照するとquestion_textの内容が得られる。

 

Django – Tutorial – ビューへのルーティング

概要

DjangoドキュメントのチュートリアルPart3では、ビューへのルーティングやテンプレートの使い方などが詳しく書かれているが、このうちURLconf~ルーティングの部分を整理する。

urls.pyの配置や書き方についてはこちら

view関数の定義

まず、polls/views.pyファイルに3つのview関数(detail, results, vote)を追加する。

いずれのビューでも動作の本質は同じ。

  • リクエストからパラメーターをquestion_idとして受け取る
  • 各ビューで想定している処理の内容に即したテキストをHttpResponseで返す
  • その際、question_idの値もテキストに含めて返す

なおテキストにquestion_idの内容を文字列として含めるために、Pythonの構文を使っている。

"... %s ..." % 変数

urls.pyの設定

追加したview関数をこれに対応したURLリクエストから呼び出すため、ルーティングを追加する。

いずれのルーティングもpollsアプリケーションのビューに関するものなので、最初に作成したpolls/urls.pyに追記する。

確認

サーバー起動状態で各URLを入力したとき、呼ばれるview関数とブラウザー上の文字列は以下のとおり。

  • http://localhost:8000/polls/34/
    views.detail
    →You’re looking at question 34.
  • http://localhost:8000/polls/34/results/
    views.results
    →You’re looking at the results of question 34.
  • http://localhost:8000/polls/34/vote
    views.vote
    →You’re voting on question 34.

URLconf~ルーティングの仕組み

たとえばhttp://ドメイン名/polls/34/というURLでリクエストがあった時、Djangoは以下のように解釈を始める。

  1. settings.pyROOT_URLCONFの設定に従って、config.urlsモジュールを読み込む(モジュールファイルはconfig/urls.py
  2. urlsモジュール中のurl_patterns配列から、パターンを1つずつ順に走査していく
  3. URLパターンが'polls/'パターンまでマッチした時、それ以前のパターンを取り除いて、polls.urlsモジュールを読み込む
  4. polls.urlsモジュールでURLパターンの'<int:question_id>/'パターンまでマッチしてその後がないとき、これに対応するviews.detailモジュールを呼び出す
  5. detailモジュールでは<int:queston_id>の内容が引数のquestion_idに渡され、ビュー内での処理に使われる

なおsettings.pyROOT_URLCONFはデフォルトで以下のように書かれていて、まずconfig.urlsが読み込まれるようになっている。

またconfig.urlsは、チュートリアルの最初の方で以下のように編集済み。

またパラメーターについては<int:question_id>と定義されているので、localhost:8000/polls/abc/のようにパラメーターが整数として解釈されない場合にはパスが見つからず、Page not foundエラーになる。

 

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