Django入門(2)では開発について記載する。
Djangoを設定後、開発を進めるに当たって躓いたところを書いていく。
モデル作成
既存テーブルを用いる
モデルを作成すると、モデルは命名則に従ったテーブルに対してデータ操作をしようとする。
しかし既にテーブル作成済みの場合はDjangoの命名則に従わずに既存のテーブル名を使いたくなる。
その際、メタオプションを用いる。
具体的には以下のように記述する。
(Meta optionsはモデル定義の中に書く)
[python title="models.py"]
class モデル名(models.Model):
モデルのフィールド設定
class Meta:
db_table = '(このモデルと紐づけたいテーブル名)'
[/python]
フィールド設定
フィールドの型
複数フィールドの組み合わせでPrimary Keyを設定できない
Djangoは複合キーをサポートしていない。
しかしモデル上でPrimary Keyを指定せずにadmin機能を使おうとすると、データ選択した際にエラー画面に遷移してしまう。
(admin機能を使わなければ大丈夫かどうかは未確認)
Multi-Column Primary Key support
回避するにはDB側のテーブルにてPrimary Key用にIDカラム(auto increment)を設け、本来のPrimary Keyのカラムにはunique indexを張る。
別スキーマのデータを参照する
アプリの使うスキーマはAだが、別スキーマBに保存されているマスタも参照させたい場合、「Django model schema multiple」などで検索してもよくわからず。
方法1:Viewにしてしまう
そこで発想を転換し、スキーマBのマスタに対してselectするviewをスキーマAに作成することでadminからマスタを参照できる事を確認できた。
(もっと良い方法があれば共有願います)
方法2:settingsで接続DBを制御する
settings.pyとDATABASE_ROUTESで接続先を切り分ける方法もある模様。
方法2はDjango側の設定だけで済むし、方法1はDB側にview追加するだけで済むので目的に応じて使い分けが必要かと思われる。
WEBサーバー
ローカルPCで起動したDjangoサーバーを公開
settings.pyでALLOWED_HOSTSの設定を変更
[code lang=text]
ALLOWED_HOSTS = ['*']
[/code]
さらにWEBサーバーを起動する際にデフォルトでは127.0.0.1で起動してしまい、他のユーザーが起動しているマシンのIPをWEBブラウザで参照しても見られない。
他のユーザーにも公開するには0.0.0.0で起動する必要がある。
[code lang=text]
python manage.py runserver 0.0.0.0:8000
[/code]
データ操作
id項目以外を用いた結合
Djangoでモデルを結合する場合は、暗黙的にprimary key であるid項目で結合している模様。
一対一 (one-to-one) 関係
多対多 (many-to-many) 関係
auto incrementしているid項目だと、リレーションが崩れやすいので値に意味を持つ一意項目で結合したい。
生SQLの実行
強引な手段ではあるが、生SQLを記述する方法がある。
以下のようにrawを使うことで生SQLの実行が可能。
[python title="views.py"]
from .models import (モデル名)
def (view名)(request):
(変数) = (モデル名).objects.raw( (SQL文字列) )
[/python]
注意点1:primary keyが必要
select結果にprimary keyが無いと
[code lang=text]
Raw query must include the primary key
[/code]
のエラーが発生する。
特にハマりやすいのが
[code lang=text]
select
m.id
...
from hogetable m
[/code]
ではエラーを回避できないこと。
[code lang=text]
select
m.id as id
...
from hogetable m
[/code]
と エイリアスを追加 することでやっとエラーが回避できた。
注意点2:like検索等で"%hoge%"を直接SQL内に書くとエラーになる
[code lang=text]
(変数) = (モデル名).objects.raw( "select colA, colB, colC from tableX where colD like '%hoge%' " )
[/code]
と書くとargumentエラーが発生してしまう。
[code lang=text]
(変数) = (モデル名).objects.raw( "select colA, colB, colC from tableX where colD like %s", tuple(["%hoge%"]) )
[/code]
と外出しすることでSQLを実行できる。