【django】テーブルの連携と外部キー

 

この記事では、テーブルの連携と外部キーについて説明します。

 

[toc]

 

テーブルに連携が必要な理由

 

ここでは2chを例に説明していきます。

 

例えば、2ch掲示板で以下の機能を作るときのケースです。

 

スレ主がスレをたてる

 

これは基本ですよね。これが無いと掲示板は成り立ちません。

 

スレ主というとアレなので、ユーザと定義しましょう。スレはスレッド、話題項目です。

 

ユーザとスレッドの2つが出てきましたね。

 

この掲示板を作るには、ユーザとスレッドの2種類のテーブルが必要になります。

 

ユーザが入力する情報を適当に並べます。

 

・名前
・メールアドレス

 

スレッドに入力する情報は、、

 

・タイトル
・投稿内容
・投稿日時
・ユーザの名前

 

スレッドの中にユーザの名前が出てきました。ユーザの名前が無いと誰が投稿したか分からないのでこれは必要ですね。

 

ユーザの名前を使うためにユーザのテーブルを参照します。

 

これがテーブル間の連携が必要な理由です。

 

テーブルの主従関係

 

外部キーの前に主従の関係を理解しましょう。

 

上の例でいうと、ユーザが主でスレッドが従です。

 

スレッドを作っていないユーザはいるけど、ユーザがいないスレッドはありません。

 

これがユーザが主である理由です。無くてはならない方を主とする。これが基本です。

 

外部キー

 

1つのユーザに対して、複数のスレッドが存在します。これを1:多の関係と言います。

 

外部キーは従のテーブルが保持するのがルールです。図にすると以下の通り。

 

 

概念を理解したところで、メッセージ投稿のシステムを作ってみます。

 

モデルの作成

 

models.py

from django.db import models

class Friend(models.Model):
    name = models.CharField(max_length=100)
    mail = models.EmailField(max_length=200)
    gender = models.BooleanField()
    age = models.IntegerField(default=0)
    birthday = models.DateField()

    def __str__(self):
        return '<Friend:id =' + str(self.id) + ',' + self.name + '(' + str(self.age) + ')>'


class Message(models.Model):
    friend = models.ForeignKey(Friend, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.CharField(max_length=300)
    pub_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '<Message:id=' + str(self.id) + ', ' + self.title + '(' + str(self.pub_date) + ')>'

    class Meta:
        ordering = ('pub_date',)

 

説明に登場したユーザとスレッドですが、ソースコードではそれぞれFriendとMessageに置き換えて読んでください。

 

Messageの中に外部キー(ForeignKey)が含まれていますね。これが上の図で説明したやつです。

 

HTMLファイルで出力するときのコードを見てみましょう。

 

message.html

<tr>
    <th>title</th>
    <th>content</th>
    <th>name</th>
    <th>datetime</th>
</tr>
{% for item in data %}
    <tr>
        <td>{{ item.title }}</td>
        <td>{{ item.content }}</td>
        <td>{{ item.friend.name }}</td>
        <td>{{ item.pub_date }}</td>
    <tr>
{% endfor %}

 

item.friend.nameとなっています。Messageクラスの中には、nameという変数はありませんでしたが、外部キーを使うことでFriendのnameを参照できるようになっています。

 

出力結果

 

board

 

下の欄で、投稿者の名前が表示できていますね。こんな感じで、掲示板って作られているみたいです。

 

以上です。お疲れ様でした。

 

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog