我想为我的表单中的所有字段设置TextInput Widget的类属性为一个值,而不必在Meta中列出它们:widgets = {....这可能吗?如何为Django ModelForm设置默认控件属性?
谢谢。在所有的领域
class PrettyWidget(forms.TextInput):
class Media:
css = {
'all': ('pretty.css',)
}
在您的形式使用新的部件:
我想为我的表单中的所有字段设置TextInput Widget的类属性为一个值,而不必在Meta中列出它们:widgets = {....这可能吗?如何为Django ModelForm设置默认控件属性?
谢谢。在所有的领域
class PrettyWidget(forms.TextInput):
class Media:
css = {
'all': ('pretty.css',)
}
在您的形式使用新的部件:
您可以覆盖的构造,以修改所有的TextInput控件:
from django import forms
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
for name, field in self.fields.items():
if field.widget.__class__ == forms.widgets.TextInput:
if 'class' in field.widget.attrs:
field.widget.attrs['class'] += ' my-class'
else:
field.widget.attrs.update({'class':'my-class'})
class Meta:
model = MyModel
可以吗用装饰器覆盖init?另外,在attrs.update()之前应该有一个if语句,因为我想设置一个默认值,而不是覆盖可能已经存在的值。 - 凯文
未经测试,但我想你可以继承自MyForm,如果你使用这很多。
与CSS类创建一个新的widget
class ContactForm(forms.Form):
subject = TextField(widget=PrettyWidget)
这感觉更Djangonic的方式来完成任务,但它并不完全看起来像什么凯文是我后... – codekoala 2010-09-24 14:43:19
一件事,我已经在过去做的是创造返回领域的lambda函数我经常使用:
from django import forms
fancy = lambda: forms.TextInput(attrs={'class': 'derp'})
class MyForm(forms.Form):
attr1 = fancy()
attr2 = fancy()
attr3 = fancy()
我不记得到底为什么我选择使用一个函数T Ø处理我的情况,但我怀疑它有一些东西需要与创建forms.TextInput对象每个表单字段的不同实例....
这是我现在要做的。有必要创建单独的forms.Select实例。 – Kevin 2010-09-26 23:59:33
您可以使用下面:
def set_attrs_for_fields(fields, default_attrs):
for field_name in fields:
field = fields[field_name]
try:
default_widget_attr = default_attrs[field.widget.__class__]
field.widget.attrs = default_widget_attr
except KeyError:
pass
class DefaultAttrForm(forms.Form):
def __init__(self, *args, **kwargs):
super(DefaultAttrForm, self).__init__(*args, **kwargs)
set_attrs_for_fields(self.fields, self.get_default_attrs())
def get_default_attrs(self):
'''
Child class should overwrite this method and return dict with example format
{forms.TextInput: {'class': 'my_value'}}
where keys, are widget classes for which default attrs will be set.
'''
raise NotImplementedError()
class DefaultAttrModelForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DefaultAttrModelForm, self).__init__(*args, **kwargs)
set_attrs_for_fields(self.fields, self.get_default_attrs())
def get_default_attrs(self):
'''
Child class should overwrite this method and return dict with example format
{forms.TextInput: {'class': 'my_value'}}
where keys, are widget classes for which default attrs will be set.
'''
raise NotImplementedError()
现在,每次你想为某个小部件使用默认attrs时,你只需要创建继承自DefaultAttrForm或DefaultAttrModelForm的类并覆盖方法get_default_attrs
。例如,对于普通的Django形式:
class MyForm(DefaultAttrForm):
my_field1 = forms.CharField(widget=forms.TextInput())
my_field2 = forms.CharField(widget=forms.PasswordInput(attrs={'my_non_default': 'Non default'}))
def get_default_attrs(self):
# all fields with widget TextInput will have
# default attrs set to {'class': 'my_value'}
return {forms.TextInput: {'class': 'my_value'},
}
In [1]: form = MyForm()
In [2]: form.fields['my_field1'].widget.attrs
Out[2]: {'class': 'my_value'}
In [3]: form.fields['my_field2'].widget.attrs
Out[3]: {'my_non_default': 'Non default'}
对于型号形式使用下列内容:
class MyModelForm(DefaultAttrModelForm):
class Meta:
model = my_model
def get_default_attrs(self):
# all fields with widget TextInput will have
# default attrs set to {'class': 'my_value'}
return {forms.TextInput: {'class': 'my_value'},
}
In [1]: form = MyModelForm()
In [2]: form.fields['my_field1'].widget.attrs
Out[2]: {'class': 'my_value'}
In [3]: form.fields['my_field2'].widget.attrs
Out[3]: {'my_non_default': 'Non default'}
对于ModelForm,我们可以使用它。
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
# change a widget attribute:
self.fields['user_permissions'].widget.attrs["size"] = 5
self.fields['user_permissions'].widget.attrs["class"] = 'form-control required'
class Meta:
model = User
你可以用装饰器重写init吗?另外,在attrs.update()之前应该有一个if语句,因为我想设置一个默认值,而不是覆盖可能已经存在的值。 – Kevin 2010-09-27 21:44:20
我认为装饰器是用于可调用的,覆盖构造函数应该通过正常的继承机制来完成。在Django中,有一些函数返回类并不罕见,这些函数通常被称为“工厂”。更新为“if”条件(未经测试)。 – 2010-09-28 15:02:40