如何创建一个带有RadioSelect字段的Django表单,并禁用一些按钮?

如何创建一个带有RadioSelect字段的Django表单,并禁用一些按钮?,django,django-models,Django,Django Models,我正在创建一个带有一组单选按钮(作为单个RadioSelect字段)的Django表单,我希望其中一些按钮变灰。然而,鉴于RadioSelect字段是表单上的单个字段,我还没有找到这样做的方法 class OrderStatusForm(forms.Form): os = Order_Status.objects.values_list('id', 'status') status = forms.ChoiceField(choices=os, widget=forms.Radi

我正在创建一个带有一组单选按钮(作为单个RadioSelect字段)的Django表单,我希望其中一些按钮变灰。然而,鉴于RadioSelect字段是表单上的单个字段,我还没有找到这样做的方法

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
有没有办法选择性地禁用单个单选按钮?或者我不必首先将禁用的选项放在列表中?

可以尝试:

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


您可以使用JavaScript在模板中执行此操作,如下所示:

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

$(函数(){
{%用于禁用%中的val}
$('input[name=“status”][value=“{{val}}}”]').attr('disabled',true);
{%endfor%}
});

假设jQuery(用于
$
)和
disable
(在
{%for%}
循环中)是传递给模板的一个变量,该变量的计算结果是希望变灰的值列表。

进一步研究发现,RadioSelect
渲染器可以替换,并作为参数传递给初始小部件创建函数。因此,我创建了自己的渲染器,并附加了一个布尔值列表,指示应该禁用哪些单选按钮

渲染器根据需要向每个单选按钮小部件添加禁用属性,然后强制unicode将小部件的属性转换为包含
disabled=“True”
值的HTML

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
来自django.utils.safestring导入标记\u safe
从django.utils.encoding导入强制\u unicode
类RandomRenderer(forms.RadioSelect.renderer):
“”“修改要在HTML中禁用的某些单选按钮,
基于外部附加的活动列表。”“”
def渲染(自):
如果不是hasattr(self,“actives”):#哦,忘了添加一个actives列表
返回self.original_render()
返回self.my_render()
def原始_渲染(自):
返回标记\u safe(u'
    \n%s\n
'%u'\n'。加入([u'
  • %s
  • ' %强制_unicode(w)表示w(在self中)() 定义我的渲染(自): 中间列表=[] 对于x,枚举中的wid(自): 如果self.actives[x]==False: wid.attrs['disabled']=True 追加(u'
  • %s
  • '%force\u unicode(wid)) finalList=mark\u safe(u'
      \n%s\n
    '%u'\n'。加入([u'
  • %s
  • ' %w代表中间列表中的w])) 回归终结者 类OrderStatusForm(forms.Form): os=订单\状态.对象.值\列表('id','Status','reason')) activeList=[True,False,True,False,True,False,] newStatus=forms.ChoiceField(widget=forms.RadioSelect( 渲染器=随机渲染器),选项=操作系统) newStatus.widget.renderer.actives=activeList

    这有点麻烦-我只是将actives列表直接粘贴到渲染器上,这很有效(喜欢Python的duck类型),但是如果我在一些构造函数中传递该列表,会更干净。不幸的是,我在这方面遇到了问题,所以选择了简单的方法

    这与我发布的内容没有什么不同-
    状态
    被视为一个字段(有多个单选按钮),并且整个内容被禁用。将代码移动到init不会改变它的影响。谢谢,这是一个有趣的方法。我不清楚如何引用每个字段-下标?或者Django是否指定了默认名称?(另外,我将在不使用JS的情况下启动该网站,并最终添加它,因为我确定了最佳使用区域。)“输入[name=“status”]”部分将找到您的所有字段,称为status,就像表单中一样。“[value=“{val}}”]”部分将选择一个特定的单选按钮。与for循环相结合,最终禁用所有必需字段。默认名称是字段“status”的名称。您仍然需要在服务器端检查它,因为有人可以修改HTML。更简单的方法是在调用super方法之前覆盖
    forms.RadioSelect的
    create\u选项
    方法,并在需要时添加
    attrs['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