2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

10 分で終わる Django の外部キーのチュートリアル

Last updated at Posted at 2020-04-01

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 のふたつのアプリを登録。

mysite/mysite/settings.py
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',
]
mysite/mysite/urls.py
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 と、アプリ名を先頭につけてからモデルを呼び出す。

mysite/cafe/models.py
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

どのビューがどのテンプレートを使うのか、ややこしくならないように、
くどいファイル名を付けている。

mysite/cafe/views.py
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 はファイルを新設する
どのパス名がどのビューを指すのか混乱しないように、くどい名前を付けている。

mysite/cafe/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 を編集し、有効化する。

mysite/cafe/admin.py
from cafe.models import NekoModel, FoodModel
from django.contrib import admin

admin.site.register(NekoModel)
admin.site.register(FoodModel)

テンプレートの作成

テンプレートを 3 つ作成。
置き場所はデフォルトのディレクトリにしたが、階層が深すぎて本当は好きじゃない。

mysite/cafe/template/cafe/nekolistview_template.html
<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>
mysite/cafe/template/cafe/foodlistview_template.html
<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>
mysite/cafe/template/cafe/nekocreateview.html
<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 でやったことの繰り返し。

mysite/negura/models.py
from django.db import models

class NeguraModel(models.Model):
    negura_name = models.CharField(max_length = 20)
    def __str__(self):
        return self.negura_name
mysite/negura/views.py
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'
mysite/negura/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('neguralist_url', views.NeguraListView.as_view(), name = 'neguralistview_path'),
]
mysite/negura/admin.py
from cafe.models import NeguraModel
from django.contrib import admin

admin.site.register(NeguraModel)

テンプレートの作成

テンプレートを 1 つ作成
置き場所はデフォルトの場所で。

mysite/negura/template/negura/neguralistview_template.html
<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/

「ねこのとうろく」リンクから登録用画面に入ると、
フォームにねこの名前を入力し、
「たべもの」と「ねぐら」はドロップダウンリストから選べるようになっている。

おしまい

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?