2011-01-09 76 views
2

我有一個包含各種類型設置的表。我想在表單中以不同的方式顯示和驗證每個設置。例如,如果設置爲整數或字符串。Django Dynamic Widget /表單字段表示

這是我的模型

class Setting(models.Model): 
    SETTING_TYPES = (
     (u'1', u'Decimal'), 
     (u'2', u'Integer'), 
     (u'3', u'String'), 
    ) 
    type = models..CharField(max_length=2, choices=SETTING_TYPES) 
    name = models.CharField(max_length=50, unique=True) 
    value = models.CharField(max_length=200) 

因此,如果類型爲1我想限制形式錄入和驗證針對的事實,我很期待小數。但如果類型是3,我需要顯示一個更大的條目形式,並根據預期字符串的事實進行驗證。

幾個地方,我可以用可能看到要做到這一點:

  1. 在自定義窗口小部件
  2. 通過重寫BaseModelFormSet類使用上的init(http://snippets.dzone.com/posts/show/7936
  3. 改變字段屬性自定義模板過濾器,將評估類型是什麼,然後通過該設置類型的自定義模板手動呈現表單
  4. 將類型和值一起存儲在jsonfield中,並使用諸如http://www.huyng.com/archives/django-custom-form-widget-for-dictionary-and-tuple-key-value-pairs/661/之類的內容來更改th e顯示和驗證設置值在一個地方..

有了選項1,我不確定我是否在'value'字段上使用自定義小部件,如果它能夠訪問'type '字段來確定如何表示'值'

我試過選項2,雖然我可以訪問表單元素,但我無法訪問表單值來確定設置的類型(也許它們沒有綁定然而?)。我認爲這條路線可能是simpliest但我需要訪問形成價值觀..

class BaseSettingFormset(BaseModelFormSet): 
    def __init__(self, *args, **kwargs): 
     super(BaseSettingFormset, self).__init__(*args, **kwargs) 
     for form in self.forms: 
      # here i would access the type value and then change the widget propeties below 
      if form.fields['type'] == 3: # DOESN"T WORK :(
       # change the widget and field properties 
       form.fields['value'].help_text='some text' 
       form.fields['value'].widget = CustomWidget() # or switch from decimal to string widgets.. 

def editProfile(request, strategy_id): 
    settingModelFormset = modelformset_factory(profile, formset=BaseSettingFormset) 

    ... retrieve the values and show them.. 

(同時發佈這個我沒有找到一個職位,可以讓我在初始化過程中的窗體綁定,因此有機會獲得值,請參閱django - how can I access the form field from inside a custom widget

選項3適用於顯示字段,但不適用於驗證任何數據。 我想我需要將它與選項2結合以在保存期間對其進行驗證。

#Custom template filter 
@register.filter(name='show_setting') 
def show_setting(form): 
    setting = field_value(form['type']) # calls another function to retrieve value (works ok) 
    # render page using custom template that can alter the form to show a small field or text area etc. 
    # can also add js validations here.. (but no server validations) 
    if setting: 
     return render_to_string('setting-'+str(setting)+'.html', { 'form': form }) 

哪種方法最好(或者有其他方法),我該如何完成它? 或者我正在做這個錯誤的方式,有沒有更多的djangoesc方式來解決我的問題?

回答

0

我相信你正在尋找的是一個custom validator傳遞到CharField的構造函數。

另一個可能更優雅的解決方案取決於具體情況,可能是讓您自己的字段類擴展CharField並重載其驗證代碼。