【django】多対多の (many-to-many) リレーション

多対多の (many-to-many) リレーションを定義するには ManyToManyField を使います

例えば、海鮮丼をつくるとき Gohan には複数の Guzai オブジェクトを持たせられます。すなわち、ある Guzai は複数のごはんの上に置けて、逆にそれぞれのごはんには複数の具材を置けるというわけです。このリレーションを表すには次のようにします:

class Guzai(models.Model):
  # ...

class Gohan(models.Model):
  # ...
  guzais = models.ManyToManyField(Guzai)

詳しい使い方:


model:

 class Guzai(models.Model):
  guzai = models.CharField(max_length=200)
  def __unicode__(self):
   returnself.guzai
  class Meta:
    ordering = ('guzai',)


 class Gohan(models.Model):
  gohan = models.CharField(max_length=200)
  guzais = models.ManyToManyField(Guzai)

  def __unicode__(self):
   return self.gohan

  class Meta:
   ordering = ('gohan',)

Sample API

>>> from Kdon.don.models import Guzai, Gohan
  
具材をつくって保存する
>>> neta1 = Guzai(guzai='ikura')
>>> neta1.save()


>>> Guzai.objects.all()
[]


>>> neta2 = Guzai(guzai='shake')
>>> neta2.save()
>>> neta3 = Guzai(guzai='uni')
>>> neta3.save()

ごはんを作って保存する
>>> mesi1 = Gohan(gohan='siromesi')
>>> mesi1.save()
>>> mesi2 = Gohan(gohan='genmai')
>>> mesi2.save()
>>> mesi3 = Gohan(gohan='kayaku')
>>> mesi3.save()

飯1(白飯)にネタ1(いくら)をのっける
>>> mesi1.guzais.add(neta1)

飯2(玄米)にネタ1とネタ2(シャケ)をのっける
>>> mesi2.guzais.add(neta1,neta2)

飯2(玄米)にネタ2(うに)をのっける
>>> mesi2.guzais.add(neta3)

新しいエビという具材を作って飯2の上にのっける
>>> new_guzai = mesi2.guzais.create(guzai='ebi')

飯1の上のネタ
>>> mesi1.guzais.all()
[]

飯2の上のネタ
>>> mesi2.guzais.all()
[, , , ]

すべての具材(エビが増えている)
>>> Guzai.objects.all()
[, , , ]

ネタ2が乗っている全てのごはん
>>> neta2.gohan_set.all()
[]

ネタ1が乗っている全てのごはん
>>> neta1.gohan_set.all()
[, ]
>>>
>>>
ネタ1が乗っている全てのごはんに飯3を足す
>>> neta1.gohan_set.add(mesi3)


ネタ1が乗っている全てのごはん
>>> neta1.gohan_set.all()
[, , ]