2016-04-29 3 views
1

私のDjangoモデルでは、残りはオプションですが、主なものになることができる値は1つだけです。私のモデルでは1つの行に特定のフィールド値を持たせる方法はありますか?

@with_author 
class BOMVersion(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True) 
    description = models.TextField(null=True, blank=True) 
    tomaterial = models.ForeignKey(Material, related_name = 'tomaterial') 

    status = models.CharField(max_length=1, choices=STATUS_CHOICES) 

BOM_CHOICES = (
    ('M','Main'), 
    ('A','Additional'), 
) 

私は残りの部分は常に追加になりながら、一つだけの行statusの値メインを持っていることを、このようなデータで、このモデルを移入することができるはずです。 (値のみを選択することができたときにそれは完全にラジオボタンの機能です。)例えば

:私はすべての値は常に追加されます追加され、別のを持っています回避策を思い付いた

1 v1 ...A 
2 v2 ...M 
3 v3 ...A 
......... 
n vn ...A 

ラジオボタンを持つUIで、ユーザーはどの値をメインにするかを選択します。

しかし、このロジックを直接Djangoモデルに適用する方法があるのだろうか?

+0

モデルに追加する方法を知らず、保存メソッドでテストを行います。このインスタンスのステータスがメインの場合は、データベース内の他のすべてのオブジェクトを追加で更新するという条件を設定できます。あなたはそこに無限ループにならないようにする必要があります。 – Shovalt

+0

フォーム要素の機能は、javascriptで実装する必要があり、好ましくはModelFormオブジェクトで検証されます。 – Shovalt

答えて

2

データベースでサポートされている場合は、partial unique indexが適しています。

CREATE UNIQUE INDEX bom_constraint ON appname_bomversion (status) WHERE status = 'M'; 

Djangoはまだ、このようなインデックスをサポートしていませんが、移行を作成することによって、それらを自分で追加することができます。PostgreSQLでは、このようになります。詳細については、this answerを参照してください。

これはデータベースレベルで制約を強制しますが、魔法のようにフォームが妥当性を完全に検証することはありません。しかし、これはすでにフォームレベルでこれに対処しているようです。

+0

実際には、複数の行に 'M 'を挿入できないような制約がありますか? "索引には述語を満たすテーブル行のみのエントリが含まれています[...]部分的な索引を使用する主な理由の1つは、共通の値の索引付けを避けることです。これらの例は、1つ以上の値が索引付けされることを期待していることを明確に示しています。 – Risadinha

+0

@Risadinha:ここでの違いは、一意の列が述語と同じであることです。 2番目の行に 'status == M 'を追加しようとしたとします。述語を満たすので、索引付けする必要があります。しかし、それを索引に追加しようとすると、 'status'がそのような行で一意であるという制約に違反します。 –

+0

説明ありがとうございます! – Risadinha