1

同じタイプの複数のオブジェクトを 1 つのデータ エントリにリンクできる django データ モデルを作成するのに問題があります。これが私の現在のモデルです:

class House(models.Model):
    name = models.CharField(max_length=200, unique=True)
    color = models.CharField(max_length=200, unique=True) 

class Config(models.Model)
   name = models.CharField(max_length=200)
   nbr_houses = models.PositiveIntegerField()
   houses = models.ManyToManyField(House) # this does not work, since I can only map a house once back to Config. 

次のことをしたい(疑似コード):

# define a new config and enforce that is should have houses.
$ a = Config(name = 'new_config', nbr_houses = 3)
# associate individual houses with this config
$ a.houses[0] = House(pk= 1)
# associate the same house a second time with this config
$ a.houses[1] = House(pk= 1)
# associate a third house to config.
$ a.houses[2] = House(pk= 2)

新しいConfigオブジェクトを作成し、new_configこの構成には 3 つの家が必要であると言います。次に、モデルが自動的にチェックして、正しい数の家屋を にリンクするように強制しますConfig。さらに、House同じ構成を 2 回参照する場合があります。

私はConfig次のように書くことを考えていました

class Config(models.Model)
   name = models.CharField(max_length=200)
   nbr_houses = models.PositiveIntegerField()
   houses = models.ManyToManyField(House, related_name='house0')
   houses1 = models.ManyToManyField(House, related_name='house1')
   houses2 = models.ManyToManyField(House, related_name='house2')
   houses3 = models.ManyToManyField(House, related_name='house3')

基本的に可能な関連付けの最大数を反映しますが、それはちょっと柔軟性がありません。これを達成するためのより良い方法は何ですか?

編集:次の使用例を想像してください: シーンの複雑さを定義できるコンピューター ゲームを書きたいとします。各シーンは に保存されますConfig。シーンごとに、xたくさんの家を配置できます。家は違いはありません。それらは単なるテンプレートです。したがって、10 軒の赤い家、2 軒の青い家、1 軒の黄色い家でシーンを構成できます。したがって、エントリごとConfigに、異なる数の家 (オブジェクト) を関連付けられるようにしたいと考えています。たぶん後で馬も登場するでしょう:)あなたがアイデアを理解してくれることを願っています.

4

1 に答える 1

5

質問が更新され、各家屋のいくつかを構成に関連付けたい可能性があることを説明しました。Django でこれを行うには、Django が中間モデルと呼ぶ新しいモデルが必要です。このような:

class ConfigHouses(model.Model):
    config = model.ForeignKey('Config')
    house = model.ForeignKey('House')
    count = model.PositiveIntegerField()
    class Meta:
        unique_together = ('config', 'house')

次に、Configクラスで a を宣言し、中間モデルをパラメーターManyToManyFieldに割り当てます。through

class Config(model.Model):
    # ...
    houses = model.ManyToManyField('House', through = 'ConfigHouses')

家を構成に追加するには、中間モデルの新しいインスタンスを作成します。

# Level 1 contains 4 red houses and 5 yellow houses
c = Config.objects.get_or_create(name = 'level-1')

red = House.objects.get_or_create(name = 'red')
ch = ConfigHouses(config = c, house = red, count = 4)
ch.save()

yellow = House.objects.get_or_create(name = 'yellow')
ch = ConfigHouses(config = c, house = yellow, count = 5)
ch.save()

上記のクエリを実行すると、データベースは次のようになります。

CONFIG TABLE
----------------
| pk | name    |
|----|---------|
|  1 | level-1 |
----------------

HOUSE TABLE
----------------
| pk | name    |
|----|---------|
|  1 | red     |
|  2 | yellow  |
----------------

CONFIGHOUSES TABLE
-------------------------------
| pk | config | house | count |
|----|--------|-------|-------|
|  1 |      1 |     1 |     4 |
|  2 |      1 |     2 |     5 |
-------------------------------

特定の構成にある特定のタイプの家屋の数を調べるには、直接、またはモデルのいずれかを介して中間テーブルにクエリを実行します。

>>> ConfigHouses.objects.get(config = c, house__name = 'red').count
4
>>> c.confighouses.get(house__name = 'red').count
4
>>> yellow.confighouses_set.get(config = c).count
5

元の答え

(元の質問では、多対多の関係に多重度が必要であることは明確ではありませんでしたが、有用な場合に備えて元の回答を残しています。)

あなたのオリジナルのアイデア (それは であるhouses必要がありますManyToManyField) は正しいアイデアです。クラスを定義する前にクラスを参照するには、クラスの名前Houseを渡す必要があるだけです。Django のドキュメントを参照してください。

まだ定義されていないモデルに関係を作成する必要がある場合は、モデル オブジェクト自体ではなく、モデルの名前を使用できます。

nbr_housesまた、誰かがフィールドを更新することを忘れずに多対多の関係を更新すると、正しくなくなる可能性があるため、フィールドを持つこともお勧めできませんnbr_houseshouses.count()関連する住宅の数を取得するために使用できます。

したがって、Configクラスは次のようになります。

class Config(models.Model)
   name = models.CharField(max_length=200)
   # The class House is not yet defined, so refer to it by name.
   houses = models.ManyToManyField('House')

また、RelatedManager インターフェイスを使用して多対多の関係を更新できます。addcreateremoveclear

config.houses = House.objects.filter(color = 'red')
于 2012-08-27T16:22:46.730 に答える