web-dev-qa-db-ja.com

Django 1.8-中間の多対多の関係-「ManytoManyField」が使用された場合の結果は何ですか?

Djangoでの関係による多対多の例:

class First(models.Model):
    seconds = models.ManyToManyField(Second, through='Middle')

class Middle(models.Model):
    first = models.ForeignKey(First)
    second = models.ForeignKey(Second)

class Second(models.Model):

中間モデルに関するドキュメント に続いて、関連するペアの1つのモデルのみにManytoManyField、上記の例のモデルファーストが含まれます。これは正しいです?

もしそうなら、どのモデルにManytoManyFieldフィールドを含める必要がありますか? ManytoManyFieldがどこにあるかによって、どちらの端からでも関係を使用することに違いはありますか?

ありがとう

編集(もっと明確にすべきだった):

関係に保存する追加のデータがあるので、Intermediaryテーブルに興味があります。

私が使用法と言うとき、私はモデルを定義することを意味するのではなく、関係を使用することを意味します(そうでなければ、Djangoそれをやらせます)。

すべての秒をファーストに関連付けたい場合、すべてのファーストを秒に関連付けるのとまったく同じですか、それともManytoManyFieldは、追加機能を導入することで、一方の方向をもう一方の方向よりも簡単にしますか?

11
StringsOnFire

運用の観点からの違いはないはずなので、唯一の違いは、モデルの定義とそれに影響を与えるもの(たとえば、Managerクラス)にあります。

また、必ずしも「スルー」クラスを定義する必要はありません。 Djangoは自動的にそれを行い、そのクラスが実際に行うのは、他の2つのテーブル内の関連する各レコードのそれぞれのIDを追跡するための3番目のテーブルを維持することだけです。その3番目のテーブルに重要なものを追加します。

たとえば、会議用のWebアプリを設計しているとします。出席者(個人と企業の両方)、および講演者とスポンサー(個人と企業の両方)に関する情報を保存することもできます。企業のモデルの一部は次のようになります。

class Company(models.Model):
    name = models.CharField(max_length=100)
    sponsored_segment = models.ForeignKey(ConferenceSegment, null=True)

class ConferenceSegment(models.Model):
    title = models.CharField(max_length=100)

しかし、それはすぐに面倒になり、スポンサーとは関係のない多くの参加企業があります。また、あなたはウェブサイトで彼らのランク/パッケージを追跡したいかもしれません(結局のところ、より大きなスポンサーはより大きな配置を得ます):

class Company(models.Model):
    name = models.CharField(max_length=100)

class ConferenceSegment(models.Model):
    title = models.CharField(max_length=100)
    sponsors = models.ManyToManyField(Company, through=u'Sponsor', related_name=u'sponsored_segments')

class Sponsor(models.Model):
    company = models.ForeignKey(Company)
    segment = models.ForeignKey(ConferenceSegment)
    rank = models.PositiveIntegerField()

ManyToManyFieldの「related_name」属性にも注意してください。これは、次の名前を使用して、ConferenceSegmentインスタンスを介してCompanyオブジェクトにアクセスできることを意味します。

c = Company.objects.get(...)
segments = c.sponsored_segments.all()

お役に立てれば。

18
JoeLinux

モデルに多対多のフィールドを追加すると、2つのモデル間のリンクを格納する別のテーブルがデータベースに作成されます。この3番目のテーブルに追加情報を格納する必要がない場合は、そのモデルを定義する必要はありません。

class First(models.Model):
    seconds = models.ManyToManyField(Second, related_name='firsts')

class Second(models.Model):
    pass

1番目と2番目のモデルで多対多のフィールドを定義することの違いは考えられません。

class First(models.Model):
    pass

class Second(models.Model):
    firsts = models.ManyToManyField(First, related_name='seconds')

どちらの場合も使用法は同じです。

firsts = my_second.firsts
seconds = my_first.seconds
1
nima