2011-12-06 14 views
1

モデルのフィールドにカスタム属性を追加する方法はありますか(サブクラス化フィールドを使用せずに)?Django - モデルフィールドのカスタム属性

テンプレートの特定のセクションに特定のフィールドのみを表示したいとします。これは、最終的に各タイプのフィールドが別のタブに表示されるためです。各フィールドにカスタム属性を追加して、どのセクション/タブを入れるべきかを特定することを考えましたが、これまでのところ、私は運がありませんでした。

私はいくつかのフィールドタイプがあります。

class Enum(set): 
    def __getattr__(self, name): 
     if name in self: 
      return name 
     raise AttributeError 

FieldTypes = Enum(["one","two","three",]) 

そして、いくつかのモデル:

class Model1(models.Model): 
    a = models.CharField() 
    b = models.ForeignKey('Model2') 
    c = models.IntegerField() 
    a.type = FieldTypes.one # this obviously doesn't work 
    b.type = FieldTypes.two # this obviously doesn't work 
    c.type = FieldTypes.three # this obviously doesn't work 

class Model2(models.Model): 
    d = models.CharField() 

とフォーム:

class Form1(forms.ModelForm): 
    class Meta: 
    model = Mode1 

テンプレート:

{% for fieldType in FieldTypes %} 
    <div class="{{fieldType}}"> 
     {% for field in form %} 
     {% if field.type = fieldType %} 
      {{ field }} 
     {% endif %} 
     {% endfor %} 
    </div> 
{% endfor %} 

しかし、これは動作しません。

アイデア?または、ページの特定のセクションに特定のフィールドのみを配置するための他の提案ですか?

ありがとうございました。

答えて

2

一般に、私はこのロジックをモデルクラス外に保ちます。モデルを助けることができれば、モデルをプレゼンテーション要素に絡ませてはいけません。フォームに表示するフィールドを選択することはプレゼンテーションの問題のようです。幸いにも、Formクラスは、データレイヤー(モデル)とプレゼンテーションレイヤー(ビューとテンプレート)の間に素敵なUIフォーカスレイヤーを提供します。

ここで私は過去にこの問題に取り組んできました。私のFormクラスでは、私は、フィールドグループのリストを作成し、タイトルとそこに含まれるフィールドの名前のリストと各:

class MyModelForm(forms.ModelForm): 
    field_groups = (
     {'name':'Group One', 'fields':('a', 'b', 'c')}, 
     {'name':'Group Two', 'fields':('d', 'e')}, 
    ) 
    class Meta: 
     model = MyModel 

は次にテンプレートで、私はグループを通じてループし、その内ループは条件付きでそれらのフィールドが含まれていました。

{% for group in form.field_groups %} 
<h3 class="groupheader">{{group.name}}</h3> 
    {% for field in form %} 
     {% if field.name in group.fields %} 
     <div class="fieldWrapper"> 
      {{ field.errors }} 
      {{ field.label_tag }}: {{ field }} 
     </div> 
     {% endif %} 
    {% endfor %} 
{% endfor %} 

これは、プレゼンテーションロジックが生活するための合理的な場所であるMyModelFormクラス内でフォームフィールドのグループ化と表示を制御することができます。

+0

それはトリックを行うように見えます。どうもありがとう。 – trubliphone

0

class Model1(models.Model): 
    a = models.CharField() 
    b = models.ForeignKey('Model2') 
    c = models.IntegerField() 

とフォーム:

class Form1(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
    super(Form1, self).__init__(*args, **kwargs) 
    self.fields['a'].type = FieldTypes.one # this obviously doesn't work 
    self.fields['b'].type = FieldTypes.two # this obviously doesn't work 
    self.fields['c'].type = FieldTypes.three # this obviously doesn't work 


    class Meta: 
    model = Mode1 
0

は、私は私のモデルクラスでこのロジックをしたいですかということ、が判明。フィールドの型は、単にどこで/どのようにそれらを表示するかを検討するだけではありません。私は以下の解決策を思いつきました。

私は、フィールドタイプのセットを保存するためにいくつかのクラスを定義した:特定のフィールド名(この例では、フィールドA」へ

class FieldType(object): 
    def __init__(self, type=None, name=None): 
     self._type = type 
     self._name = name 

    def getType(self): 
     return self._type 

    def getName(self): 
     return self._name 

class FieldTypeList(deque): 
    def __getattr__(self,type): 
     for ft in self: 
      if ft.getType() == type: 
       return ft 
     raise AttributeError 

FieldTypes = FieldTypeList([FieldType("ONE","The Name Of Field One"),FieldType("TWO","The Name Of Field Two")]) 

とフィールドタイプからマッピングのセットをそれぞれ有するいくつかのモデルDは2 ' '型である」、 'B' 及び 'C' 型である 'ONE' およびフィールド'):

class ParentModel(models.Model): 
    _fieldsByType = {} 

    a = models.CharField() 
    b = models.CharField() 

    def __init__(self, *args, **kwargs): 
     super(ParentModel, self).__init__(*args, **kwargs) 
     for ft in FieldTypes: 
     self.setFieldsOfType(ft, []) 
     self.setFieldsOfType(FieldTypes.ONE, ['a','b']) 

    def setFieldsOfType(self,type,fields): 
    typeKey = type.getType() 
    if typeKey in self._fieldsByType: 
     self._fieldsByType[typeKey] += fields 
    else: 
     self._fieldsByType[typeKey] = fields 

class ChildModel(ParentModel): 
    _fieldsByType = {} # not really sure why I have to repeat this attribute in the derived class 

    c = models.CharField() 
    d = models.CharField() 

    def __init__(self, *args, **kwargs): 
    super(ChildModel, self).__init__(*args, **kwargs) 
    self.setFieldsOfType(FieldTypes. ['c']) 
    self.setFieldsOfType(FieldTypes. ['d']) 

私は基本的な形態を有する:

class MyForm(forms.ModelForm): 
    class Meta: 
    model = ChildModel 

特定の形式(ノート、そのクラスMetaを経由して、フォームからモデルへのアクセス)から指定されたタイプのすべてのフィールドを返すために、カスタムフィルタ:

@register.filter 
def getFieldsOfType(form,type): 
    return form.Meta.model._fieldsByType[type.getType()] 

そして、それを引っ張ってようやく、テンプレートすべて一緒に(テンプレートはMyFormとFieldTypesを取ります):

{% for type in types %} 
    <div id="{{type.getType}}"> 
     {% with fieldsOfType=form|getFieldsOfType:type %} 
     {% for field in form %} 
      {% if field.name in fieldsOfType %} 
      <p> 
       {{ field.errors }} 
       {{ field.label_tag }}: {{ field }} 
      </p> 
      {% endif %} 
     {% endfor %} 
     {% endwith %} 
    </div> 
    {% endfor %}