2011-08-12 22 views
3

我正在用一組單選按鈕創建一個Django表單(作爲單個RadioSelect字段),並且我想讓的某些按鈕變灰。但是,鑑於RadioSelect字段是表單上的單個字段,我還沒有找到一種方法來做到這一點。如何使用RadioSelect字段創建Django表單,並禁用了一些按鈕?

class OrderStatusForm(forms.Form): 
    os = Order_Status.objects.values_list('id', 'status') 
    status = forms.ChoiceField(choices=os, widget=forms.RadioSelect()) 

def makeForm(): 
    newForm = OrderStatusForm() 
    # next line disables all radio buttons. 
    newForm.fields['status'].widget.attrs['disabled'] = True 

是否有某種方式來選擇性禁用個別單選按鈕?或者我只是不得不將禁用選項放在首位呢?

回答

6

進一步的研究表明,RadioSelect renderer可以將替換爲,並作爲參數傳入初始窗口小部件創建函數。所以我創建了我自己的渲染器,並附加了一個布爾值列表,指出哪些單選按鈕應該被禁用。

渲染器增加了一個禁用屬性根據需要每個單選按鈕插件,則force_unicode轉動部件的屬性成HTML,包括一個disabled="True"值。

from django.utils.safestring import mark_safe 
from django.utils.encoding import force_unicode 

class RandomRenderer(forms.RadioSelect.renderer): 
    """ Modifies some of the Radio buttons to be disabled in HTML, 
    based on an externally-appended Actives list. """ 
    def render(self): 
     if not hasattr(self, "actives"): # oops, forgot to add an Actives list 
      return self.original_render() 
     return self.my_render() 

    def original_render(self): 
     return mark_safe(u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' 
      % force_unicode(w) for w in self])) 

    def my_render(self): 
     midList = [] 
     for x, wid in enumerate(self): 
      if self.actives[x] == False: 
       wid.attrs['disabled'] = True 
      midList.append(u'<li>%s</li>' % force_unicode(wid)) 
     finalList = mark_safe(u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' 
      % w for w in midList])) 
     return finalList 

class OrderStatusForm(forms.Form): 
    os = Order_Status.objects.values_list('id', 'status', 'reason') 
    activeList = [True, False, True, False, True, False,] 
    newStatus = forms.ChoiceField(widget=forms.RadioSelect(
     renderer=RandomRenderer), choices=os) 
    newStatus.widget.renderer.actives = activeList 

這是一個小缺憾 - 我只是直接粘在活性名單上的渲染,其工作(愛Python的鴨打字),但如果我通過在一些構造函數列表會更乾淨。不幸的是我遇到了問題,所以採取了簡單的方法。 :)

1

也許嘗試:

status = forms.ChoiceField(choices=os, widget=forms.RadioSelect(attrs={'disabled':'disabled'})) 

class OrderStatusForm(forms.Form): 
    def __init__(self, *args, **kwargs): 
     super(OrderStatusForm, self).__init__(*args, **kwargs) 
     self.fields['status'].widget.attrs['disabled'] = 'disabled' 

    os = Order_Status.objects.values_list('id', 'status') 
    status = forms.ChoiceField(choices=os, widget=forms.RadioSelect()) 
+0

這與我發佈的內容沒有什麼不同 - 'status'被認爲是一個*單個字段*(帶有多個單選按鈕),整個事物都被禁用。只是將代碼移動到* init *並不會改變它的影響。 –

0

你能做到這一點與JavaScript的模板,像這樣的東西:

<script> 
    $(function() { 
     {% for val in disable %} 
     $('input[name="status"][value="{{ val }}"]').attr('disabled', true); 
     {% endfor %} 
    }); 
</script> 

假設你有jQuery(對於$)和disable(在{% for %}廁所p)是你傳遞給模板的變量,它將計算出你想要變灰的值列表。

+0

謝謝,這是一個有趣的方法。我不清楚我將如何*引用*每個字段 - 下標?或者Django分配一個默認名稱? (另外,我在沒有JS的情況下啓動站點,並最終添加它,因爲我確定了最佳用途的區域)。 –

+0

'input [name =「status」]'部分將會找到所有的字段,稱爲狀態,就像在表單中一樣。 '[value =「{{val}}」]'部分將選擇一個特定的單選按鈕。結合for循環,您最終會禁用所有必填字段。默認名稱是該字段的名稱 - '狀態'。 –

+0

你仍然需要檢查它的服務器端,因爲有人可以修改HTML。 – Rory

相關問題