2017-05-25 12 views
0

私は次のモデルがあります。それらの中に複数のFruitオブジェクトを持つことができますDjangoのモデル関係の最善の解決策

BasketFruit

Basketを、そしてFruitは単一Basketに属します。各Fruitは、手動で注文することができます。一覧に表示されるときに、保存された順序が表示されます。ここまでは順調ですね。

class Basket (models.Model): 
    # A fruit basket 
    name = models.CharField(max_length=100) 
    is_virtual = models.BooleanField(default=False) 
    # This is just a badly constructed example of how a list 
    # of basket primary keys are saved when creating the virtual basket 
    # This is only for demonstration purposes to solve the overall modelling issue 
    virtual_baskets = models.TextField(null=True) 

class Fruit (models.Model): 
    # The basket this fruit belongs to 
    basket = models.ForeignKey("Basket", related_name="fruits", on_delete=models.CASCADE) 

    # Manually sorted order 
    order = models.PositiveIntegerField(default=0) 

しかし、ユーザーはあなたが少しのルールを破って終了した既存の、本当のバスケット、外の仮想コンボバスケットを作成することができますis_virtual呼ばBasket上のフラグがあります:仮想バスケットは実際に組み合わせることができます2つのバスケットからのBaskets、したがってFruitの2つが存在します。これらのバスケットにあるFruitを手動でソートして並べ替えることができるようにするには、元のバスケットの順序を上書きしないでください。一例として、

Basket Aは順番に、含まれています:アップル、バナナ

Basket Bが含まれ、順番に:オレンジ、ブドウは

私は今、表示されるでしょう仮想Basket Cを作成したいです

アップル、ブドウ、バナナ、オレンジ

覚えておくべき注意:バーチャルバスケットは、他のさまざまなバスケットの結果を単純に結合することです。ユーザーにはそれでも有効なバスケットで、果物を再注文できるはずです。

この注文関係をモデル化するにはどうすればよいですか?新しいモデルを追加することを検討しています:

class FruitAppearance (models.Model): 
    # The basket this appearance is tied to 
    basket = models.ForeignKey("Basket", related_name="manually_sorted_fruits", on_delete=models.CASCADE) 

    # The fruit it represents 
    fruit = models.ForeignKey("Fruit", on_delete=models.CASCADE) 

    # Order 
    order = models.PositiveIntegerField(default=0) 

私はそれを正しく考えていますか?より良い方法がありますか?既存のFruitBasketモデルのManyToManyFieldを使用する必要がありますか?

+0

フルーツは単一のバスケットに属します。 –

+0

正しい、それは単一の実際のバスケットにしか属していませんが、バーチャルバスケットで異なる方法で提示することができます – strangetimes

+0

バーチャルバスケットはもちろん保存することができ、手動のフルーツオーダーはそれにとどまらなければなりません – strangetimes

答えて

0
class Basket(models.Model): 
    name = models.CharField(max_length=100) 
    fruits = models.ManyToMany("Fruit", through="FruitBasket") 
    ... 

class Fruit(models.Model): 
    ... 

class FruitBasket(models.Model: 
    basket = models.ForeignKey("Basket", on_delete=models.CASCADE) 
    fruit = models.ForeignKey("Fruit", on_delete=models.CASCADE) 
    order = models.PositiveIntegerField(default=0) 
    ... 

あなたには、いくつかのデータの冗長性を持つことになりますが、すべてのバスケットに果物のための別の順序番号を設定することができるかもしれこの方法です。

+0

ありがとうございます、私は疑問に思っていますが、ここのFruitBasketは、私が作成したFruitAppearanceモデルクラスとまったく同じです。私が見る唯一の違いは、あなたがバスケットに追加された冗長性(あなたが言ったように)が違いを生むことはないでしょうか? – strangetimes

+0

うん、フルーツ冗長性はまったく異なるバスケット(例えば、レモンはバスケットAではオーダーレベル1、バスケットBではオーダーレベル4)の1つの果物に対して異なるオーダー値を設定できるものです。この冗長性がなければ、果物の固定注文レベルのみを設定することができます。 –

+0

私は.. DBモデルレベルでクラスだけで目的の中間テーブルを作成するとしますが、バケットからアクセス可能な 'fruits'プロパティは、プログラムでこれらのプロパティにアクセスしたり設定したりすることができます。もちろん。ありがとう、私はそれが残念だが、それを動作させるためにモデルに唯一の合理的な追加だと思う! – strangetimes

0

私は以下を提案します。 モデルバスケットとバーチャルバスケットを分けて、その結果、フィールドバーチャルを削除します。

したがって、各フルーツは1つのバスケット(ForeignKey)に属しますが、同時に複数のバーチャルバスケット(ManyToManyField)に属します。 manytomanyフィールドでは、パラメータthroughtを使用し、その特定のバーチャルバスケットの果物の注文のみを格納する別のモデルを組み込みます。

class Fruit (models.Model): 
    # The basket this fruit belongs to 
    basket = models.ForeignKey("Basket", related_name="fruits", on_delete=models.CASCADE) 
    virtual_basket = models.ManyToManyField(Fruit, through='FruitOrdering') 

    # Manually sorted order 
    order = models.PositiveIntegerField(default=0) 
+0

それは悲しいことに実行可能な解決策ではありません。果物は常に存在し、実際に作られた実際のバスケットによって所有されます。上記は実際のアプリケーションがやろうとしている簡単な例なので、実際のアプリは複雑な検索フィルタを作成し、既存のリストからスマートリストを作成します。さまざまなアカウントやプロバイダから連絡先が来た連絡先アプリを考えてみましょう。また、その中から仮想リストを作成します。各プロバイダは連絡先を注文します。連絡先はスマートリスト表現で並べ替えることができます。 – strangetimes

関連する問題