在Django中无论何种field,都有一个widget的属性:
class Field(object): widget = TextInput # Default widget to use when rendering this type of Field. hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
如上所示,widget默认是TextInput。
而TextInput是一个继承Input的一个类:
class TextInput(Input): input_type = 'text' def __init__(self, attrs=None): if attrs is not None: self.input_type = attrs.pop('type', self.input_type) super(TextInput, self).__init__(attrs)
往上接着找,Input继承于Widget,不同于Widget的是它有个input_type。当继承Input时需要指明input_type,像上面的TextInput一样指明为'text',类似的,PasswordInput则将其指明为'password'。
class Widget(six.with_metaclass(RenameWidgetMethods)): needs_multipart_form = False # Determines does this widget need multipart form is_localized = False is_required = False supports_microseconds = True def __init__(self, attrs=None): if attrs is not None: self.attrs = attrs.copy() else: self.attrs = {}
在Widget中有个attrs的属性,这个属性其实可以用来设置对应field的html属性。这个属性在Widget的render里会被引用。
所以如果你需要设置某个字段的html属性时,可以这么做:
field = forms.CharField() field.widget.attrs['readonly']='true'
如果是一个这样的form:
from user.models import User from django import forms class RegisterForm(forms.ModelForm): class Meta: fields = ('first_name', 'last_name', 'email', 'username',)
你需要这样才能设置field的attrs:
for field in form: field.field.widget.attrs['readonly']='false'
为什么要这样呢?因为ModelForm的Field是一个BoundField:
class BoundField(object): "A Field plus data" def __init__(self, form, field, name): self.form = form self.field = field self.name = name self.html_name = form.add_prefix(name) self.html_initial_name = form.add_initial_prefix(name) self.html_initial_id = form.add_initial_prefix(self.auto_id) if self.field.label is None: self.label = pretty_name(name) else: self.label = self.field.label self.help_text = field.help_text or '' self._initial_value = UNSET
BoundField不像CharField或其他一般的Field,并不是直接继承于Field。所以当你需要获得BoundField的Field的对象的时候,需要使用它的field的属性。