Django: モデル間のリレーションを定義する方法

2010年2月14日

RDBの世界では、正規化の際にテーブルとテーブルの対応関係を定義することがあります。 Djangoが採用しているO/Rマッパの世界でもリレーションを定義することが可能で、以下2つの メソッドが用意されています。

例として、Djangoの既存んモデルクラスであるUserを拡張する例を記述いたします。


  • models.ForeignKey(User, unique=True)

    この例は、Userの1レコードに対して1つの拡張レコードを対応付けています。 つまり、ユーザID(主キー)が確定すると、ひとつのレコードが決定することを意味します。

  • models.ForeignKey(User)

    この例は、Userの1レコードに対して、複数の拡張レコードが対応付けられます。 つまり、ユーザID(主キー)が確定すると、複数のレコードが抽出されます。

  • models.ManyToManyField(User)

    この例は、複数のUserレコードそれぞれに対して、複数の拡張レコードが対応付けられます。 つまり、ある拡張レコードに対して、複数のユーザID(主キー)が対応付けられる可能性があるし、 あるユーザID(主キー)に対して、複数の拡張レコードが対応付けられる可能性があります。


例えば、2番目のケースを用いて、 Userの拡張モデルUserExtendedInfoモデルを定義すると以下のようになります。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from django.db import models 
from django.contrib.auth.models import User 

class UserExtendedInfo(models.Model): 
    user = models.ForeignKey(User, unique=True) 
    gender = models.CharField(u"Gender", 
                                    choices=[("male", "Male"), ("female", "Female")], max_length=32) 
    birthday = models.DateField(u"Date of birth") 
    class Meta: 
        verbose_name = "Extended User Infomation"

この場合、UserExtendedInfoモデルのレコードを複数作成して、それらから 重複して同一のUser IDを指定することはできません。

複数レコードから重複を許してUser IDを関連づけたい場合は、上記「unique=True」属性を 削除するか、Falseにしましょう。


管理者パネル(Admin画面)では、上記のように設定しておくと、既存ユーザ群のリストボックスが 表示され、そこからユーザを選択することができるようになります。「unique=True」としている 場合は、複数レコードから同一ユーザを選択してSaveしようとすると、 エラーで設定することができないようになります。