class ChoiceInput(SubWidget):
"""
An object used by ChoiceFieldRenderer that represents a single
<input type='$input_type'>.
"""
input_type = None # Subclasses must define this
def __init__(self, name, value, attrs, choice, index):
self.name = name
self.value = value
self.attrs = attrs
self.choice_value = force_text(choice[0])
self.choice_label = force_text(choice[1])
self.index = index
if 'id' in self.attrs:
self.attrs['id'] += "_%d" % self.index
def __str__(self):
return self.render()
def render(self, name=None, value=None, attrs=None, choices=()):
if self.id_for_label:
label_for = format_html(' for="{0}"', self.id_for_label)
else:
label_for = ''
attrs = dict(self.attrs, **attrs) if attrs else self.attrs
return format_html(
'<label{0}>{1} {2}</label>', label_for, self.tag(attrs), self.choice_label
)
def is_checked(self):
return self.value == self.choice_value
def tag(self, attrs=None):
attrs = attrs or self.attrs
final_attrs = dict(attrs, type=self.input_type, name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return format_html('<input{0} />', flatatt(final_attrs))
@property
def id_for_label(self):
return self.attrs.get('id', '')
我们先了解html的radio标签。
<form>
<label for="male"> <input type="radio" name="sex" id="male"/> Male </label>
<br />
<label for="female"> <input type="radio" name="sex" id="female"/> Female </label>
</form>
ChoiceInput类,负责输出一行<label>语句。
着重看render函数的输出:
return format_html(
'<label{0}>{1} {2}</label>', label_for, self.tag(attrs), self.choice_label
)
label_for 是html中label标签中的for属性。
self.tag(attrs)负责输出<input>标签。
choice_label则负责label标签的展示文本。
label_for的属性值是由id_for_label类属性指定的,id_for_label则是尝试通过attrs.id属性。
self.attrs.get('id', '')
注意__init__方法中, 如果在attrs参数指定了id, 它会自动添加index参数值的后缀。
然后进入函数tag(),增加type, name, value,checked='checked'属性。
回到__init__函数, 依次解释下每个参数的作用。
name: 负责input的name属性
value: 负责判断checked='checked'属性
attrs: 负责input的属性。
choice: 格式为(choice_value, choice_label), 分别表示input的value属性和label的文本。
index:负责如果attrs参数指定了id,则添加id的后缀。
class RadioChoiceInput(ChoiceInput):
input_type = 'radio'
def __init__(self, *args, **kwargs):
super(RadioChoiceInput, self).__init__(*args, **kwargs)
self.value = force_text(self.value)
RadioChoiceInput重新指定了input_type值, 并且重写了__init__方法,作用是将value改为文本 格式。
class CheckboxChoiceInput(ChoiceInput):
input_type = 'checkbox'
def __init__(self, *args, **kwargs):
super(CheckboxChoiceInput, self).__init__(*args, **kwargs)
self.value = set(force_text(v) for v in self.value)
def is_checked(self):
return self.choice_value in self.value
CheckboxChoiceInput重新指定input_type值。并且重写了is_checked( )和__init__方法,因为checkbox是可以多选的,所以value值是列表型的。