所以我正在使用jQuery UI来skin the radio buttons,但我不能让Django按照必须的方式呈现我的表单。
我需要这个结构:
<table>
<tr>
<td><label for="notify_new_friends">Notify when new friends join</label></td>
<td class="radio">
<input type="radio" name="notify_new_friends" id="notify_new_friends_immediately" value="1" checked="checked"/><label for="notify_new_friends_immediately">Immediately</label>
<input type="radio" name="notify_new_friends" id="notify_new_friends_never" value="0"/><label for="notify_new_friends_never">Never</label>
</td>
</tr>
</table>
总而言之,我需要一个班级(广播)中的单选按钮,他们有input
和label for
。
当我使用{{ profile_form.notify_new_friends }}
在我的模板中呈现表单时,我得到以下内容:
<ul>
<li><label for="id_notify_new_friends_0"><input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /> Immediately</label></li>
<li><label for="id_notify_new_friends_1"><input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /> Never</label></li>
</ul>
除了列表部分之外,这正是我想要的。所以我试着在它上面循环,这给了我不同格式的标签:
{% for item in profile_form.notify_new_friends %}
{{ item }}
{% endfor %}
给了我:
<label><input type="radio" name="notify_new_friends" value="0" /> Immediately</label>
<label><input type="radio" name="notify_new_friends" value="1" /> Never</label>
所以这里的问题是它停止使用label for
并开始只使用label
来包装它。
我也尝试过这样的事情,但label
和label_tag
不会渲染任何内容。
{{ profile_form.notify_new_friends.0 }}
{{ profile_form.notify_new_friends.0.label_tag }}
{{ profile_form.notify_new_friends.0.label }}
所以有人知道如何正确渲染这个!?
仅供参考,这是我的forms.py:
self.fields['notify_new_friends'] = forms.ChoiceField(label='Notify when new friends join', widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
答案 0 :(得分:7)
在我的代码中,我发现从
更改小部件forms.RadioSelect
到
forms.RadioSelect(attrs={'id': 'value'})
奇怪地导致生成的tag
值包含id
属性以及附加项的索引。如果你使用
{% for radio in form.foo %}
<li>
{{ radio }}
</li>
{% endfor %}
在表单中,您label
缠绕input
。如果您想要更加传统的input
后跟label
,则需要执行以下操作:
{% for radio in form.value %}
<li>
{{ radio.tag }}
<label for="value_{{ forloop.counter0 }}">{{ radio.choice_label }}</label>
</li>
{% endfor %}
答案 1 :(得分:2)
不幸的是,这比它应该更复杂,似乎你需要覆盖至少2个类:RadioRenderer
和RadioInput
。以下内容可以帮助您入门,但您可能需要稍微调整一下。
首先创建一个自定义单选按钮输入小部件。我们重写render方法的唯一目的是摆脱令人讨厌的结构Django强制执行(<label><input /></label>
)而我们想要我们的(<label /><input />
):
class CustomRadioInput(RadioInput):
def render(self, name=None, value=None, attrs=None, choices=()):
name = name or self.name
value = value or self.value
attrs = attrs or self.attrs
if 'id' in self.attrs:
label_for = ' for="%s_%s"' % (self.attrs['id'], self.index)
else:
label_for = ''
choice_label = conditional_escape(force_unicode(self.choice_label))
return mark_safe(u'%s<label%s>%s</label>' % (self.tag(), label_for, choice_label))
现在我们需要覆盖RadioRenderer
以便:
<li>
包装每个输入字段并<ul>
包装所有输入字段:这些方面应该做的事情:
class RadioCustomRenderer(RadioFieldRenderer):
def __iter__(self):
for i, choice in enumerate(self.choices):
yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i)
def __getitem__(self, idx):
choice = self.choices[idx]
return CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
def render(self):
return mark_safe(u'%s' % u'\n'.join([u'%s' % force_unicode(w) for w in self]))
最后指示Django使用自定义渲染器
notify_new_friends = forms.ChoiceField(label='Notify when new friends join', widget=forms.RadioSelect(renderer=RadioCustomRenderer), choices=NOTIFICATION_CHOICES)
请记住:现在输出单选按钮和包含<td>
,因此您需要在模板中围绕它创建一个表格,这些内容如下:
<table>
<tr>
<td><label for="{{field.auto_id}}">{{field.label}}</label></td>
<td>{{ field.errors }} {{field}}</td>
</tr>
</table>
答案 2 :(得分:1)
由于它似乎不是一个好方法,我选择使用jQuery重新排列生成的代码。
// First remove the ul and li tags
$('.radio ul').contents().unwrap();
$('.radio li').contents().unwrap();
// Then move the input to outside of the label
$('.radio > label > input').each(function() {
$(this).parent().before(this);
});
// Then apply the jQuery UI buttonset
$( ".radio" ).buttonset();
这使它来自:
<ul>
<li><label for="id_notify_new_friends_0"><input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /> Immediately</label></li>
<li><label for="id_notify_new_friends_1"><input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /> Never</label></li>
</ul>
到:
<input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /><label for="id_notify_new_friends_0"> Immediately</label></li>
<input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /><label for="id_notify_new_friends_1"> Never</label></li>
我的jQuery UI样式工作正常。
答案 3 :(得分:0)
Try like this , I got it..
from django.forms.widgets import RadioFieldRenderer
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
class RadioCustomRenderer( RadioFieldRenderer ):
def render( self ):
return mark_safe(u'%s' % u'\n'.join([u'%s' % force_unicode(w) for w in self]))
in form
widgets = {
'validity': forms.RadioSelect(renderer=RadioCustomRenderer),
}
答案 4 :(得分:0)
如果有人偶然发现了这个问题,只想渲染不带ul的单选按钮,则应遵循此链接。
https://docs.djangoproject.com/en/3.1/ref/forms/widgets/#selector-widgets
以下示例。
{% for radio in myform.beatles %}
<div class="myradio">
{{ radio }}
</div>
{% endfor %}