2020-04-01 作成: windows10/Python-3.8.2-amd64/Django-3.0.4
Django の外部キーについての日本語の情報は、ネットでも豊富ではありません。
しかし普通は、「好きな食べ物」と「住所録」は、別のアプリにするはずで、
外部キーの使い方は基本必修項目なのだろうと思います。
同じデータベース内と、外部のデータベースへの外部キーについて、
簡単なチュートリアルを作成しました。
複数のデータベースを相互に関連付ける方法を手軽に知りたい、という人向きです。
- ねこカフェ用のねこ管理アプリ cafe
- ねこの名前のテーブルと、好きな食べ物のテーブルをつくり、外部キーで関連付ける。
- ねこの住所録のアプリ negura
- ねこのすみかのデータベースを作る。cafe アプリから外部キーで呼ばれる。
なお、Django を初めて使う人は、まず基本編のチュートリアルを読んでください。
10 分で終わる Django の実用チュートリアル
前準備
プロジェクトの作成
ソースを置きたい場所で以下を実行しプロジェクトを新規作成。
django-admin startproject mysite
作成したディレクトリ mysite に入ってアプリケーションを 2 つ、新規作成。
cd mysite
python manage.py startapp cafe
python manage.py startapp sumika
ここまでのファイルの配置はこうなる
mysite/
mysite/
__pycashe__/ <- 気にしなくていい
setting.py, urls.py など *.py が 5 個
neko/
migrations/ <- 気にしなくていい
models.py, views.py など *.py が 6 個
sumika/
migrations/ <- 気にしなくていい
models.py, views.py など *.py が 6 個
manage.py
プロジェクトを構成するアプリの登録
cafe と negura のふたつのアプリを登録。
INSTALLED_APPS = [
'cafe.apps.CafeConfig',
'negura.apps.NeguraConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('cafe/', include('cafe.urls')),
path('negura/', include('negura.urls')),
path('admin/', admin.site.urls),
]
アプリの実装
cafe アプリの作成
モデル、ビュー、url の作成
neko_food は、cafe アプリ内の同一データベース内での外部キー
neko_negura は、negura アプリ、つまり隣のアプリの別データベースへの外部キー
def __str__(self):
メソッドは、ForeignKey を使ったとき、django の汎用ビューでは普通は必要になる。
このメソッドをオーバーライドしておかないと、ブラウザに表示したときに、
さんま
ではなく food_name.object(1)
のようにインスタンスの名前が表示されてしまう。
このメソッドのおかげで、CreateView や FormView を使うときに、プルダウンリストに文字列が表示される。
neko_negura は、外のアプリからモデルを引っ張ってきているので、
negura.NeguraModel
と、アプリ名を先頭につけてからモデルを呼び出す。
from django.db import models
from negura.models import NeguraModel
class NekoModel(models.Model):
neko_name = models.CharField(max_length = 20)
neko_food = models.ForeignKey('FoodModel', null = True,on_delete = models.SET_NULL)
neko_negura = models.ForeignKey('negura.NeguraModel', null = True,on_delete = models.SET_NULL)
class FoodModel(models.Model):
food_name = models.CharField(max_length = 20)
def __str__(self):
return self.food_name
どのビューがどのテンプレートを使うのか、ややこしくならないように、
くどいファイル名を付けている。
from django.views import generic
from .models import NekoModel, FoodModel
class NekoListView(generic.ListView):
model = NekoModel
context_object_name = 'nekolistview_context'
template_name = 'cafe/nekolistview_template.html'
class NekoCreateView(generic.CreateView):
model = NekoModel
context_object_name = 'nekocreateview_context'
template_name = 'cafe/nekocreateview_template.html'
fields = ['neko_name', 'neko_food', 'neko_negura']
success_url = '/cafe/nekolist_url'
class FoodListView(generic.ListView):
model = FoodModel
context_object_name = 'foodlistview_context'
template_name = 'cafe/foodlistview_template.html'
urls.py はファイルを新設する
どのパス名がどのビューを指すのか混乱しないように、くどい名前を付けている。
from django.urls import path
from . import views
urlpatterns = [
path('nekolist_url', views.NekoListView.as_view(), name = 'nekolistview_path'),
path('nekocreate_url', views.NekoCreateView.as_view(), name = 'nekocreateview_path'),
path('foodlist_url', views.FoodListView.as_view(), name = 'foodlistview_path'),
]
食べ物や住所の入力用ビューは、チュートリアルの手数が多くなるので作成しない。
代わりに admin 画面から入力するため、admin.py を編集し、有効化する。
from cafe.models import NekoModel, FoodModel
from django.contrib import admin
admin.site.register(NekoModel)
admin.site.register(FoodModel)
テンプレートの作成
テンプレートを 3 つ作成。
置き場所はデフォルトのディレクトリにしたが、階層が深すぎて本当は好きじゃない。
<h1>ねこのいちらん</h1>
<table>
{% for neko_param in nekolistview_context %}
<tr>
<td>{{ neko_param.neko_name }}</td>
<td>{{ neko_param.neko_food.food_name }}</td>
<td>{{ neko_param.neko_negura.negura_name }}</td>
</tr>
{% endfor %}
</table>
<p><a href = "{% url 'foodlistview_path' %}">ねこのたべもの</a></p>
<p><a href = "{% url 'neguralistview_path' %}">ねこのねぐら</a></p>
<p><a href = "{% url 'nekocreateview_path' %}">ねこのとうろく</a></p>
<h1>ねこのたべもの</h1>
<table>
{% for food_param in foodlistview_context %}
<tr>
<td>{{ food_param.food_name }}</td>
</tr>
{% endfor %}
</table>
<p><a href = "{% url 'nekolistview_path' %}">ねこのいちらん</a></p>
<h1>ねこのとうろく</h1>
<form method = "post">
{% csrf_token %}
{{ form.as_p }}
<input type = "submit" value = "とうろく" />
</form>
<p><a href = "{% url 'nekolistview_path' %}">ねこのいちらん</a></p>
negura アプリの作成
モデル、ビュー、url の作成
基本的にはさきほどの cafe でやったことの繰り返し。
from django.db import models
class NeguraModel(models.Model):
negura_name = models.CharField(max_length = 20)
def __str__(self):
return self.negura_name
from django.views import generic
from .models import NeguraModel
class NeguraListView(generic.ListView):
model = NeguraModel
context_object_name = 'neguralistview_context'
template_name = 'negura/neguralistview_template.html'
from django.urls import path
from . import views
urlpatterns = [
path('neguralist_url', views.NeguraListView.as_view(), name = 'neguralistview_path'),
]
from cafe.models import NeguraModel
from django.contrib import admin
admin.site.register(NeguraModel)
テンプレートの作成
テンプレートを 1 つ作成
置き場所はデフォルトの場所で。
<h1>ねこのねぐら</h1>
<table>
{% for negura_param in neguralistview_context %}
<tr>
<td>{{ negura_param.negura_name }}</td>
</tr>
{% endfor %}
</table>
<p><a href = "{% url 'nekolistview_path' %}">ねこのいちらん</a></p>
仕上げ
マイグレーションと admin の設定
マイグレーションしたあとは、admin サイト用の管理者を作成し、
admin 画面にアクセスできるようにしておく。
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
HTTP サーバーの起動と初期データの入力
開発用のサーバーを起動する。デフォルトで起動しているので、ポート番号は 8000。
python manage.py runserver
ブラウザで以下にアクセスして admin 画面を出す。
「たべもの」、「すみか」のふたつは、このアプリでは直接入力できないので、admin 画面から入力する。
http://localhost:8000/admin/
たとえば、たべものは、「さんま」「かりかり」、すみかは、「だんぼーる」「もうふ」など。
動作確認
以下を入力すると、ねこのリストが出る。
最初は登録されたねこがいないので、表にはないっていない。
http://localhost:8000/neko/
「ねこのとうろく」リンクから登録用画面に入ると、
フォームにねこの名前を入力し、
「たべもの」と「ねぐら」はドロップダウンリストから選べるようになっている。
おしまい