我现在才使用Django几周了,所以我可能会遇到各种各样的错误,但是:
我有一个基本的ModelForm,我将一些样板文件放入其中以使它们尽可能保持DRY,而我所有的实际ModelForms只是该基本表单的子类。这对于error_css_class = 'error'
和required_css_class = 'required'
很有用,但是formfield_callback = add_css_classes
不能像我期望的那样工作。
表格
# snippet I found
def add_css_classes(f, **kwargs):
field = f.formfield(**kwargs)
if field and 'class' not in field.widget.attrs:
field.widget.attrs['class'] = '%s' % field.__class__.__name__.lower()
return field
class BaseForm(forms.ModelForm):
formfield_callback = add_css_classes # not working
error_css_class = 'error'
required_css_class = 'required'
class Meta:
pass
class TimeLogForm(BaseForm):
# I want the next line to be in the parent class
# formfield_callback = add_css_classes
class Meta(BaseForm.Meta):
model = TimeLog
最终目标是在带有datefield/timefield/datetimefield类的表单上拍一些jquery datetime选择器。我希望应用程序中的所有日期时间字段都使用相同的小部件,因此我选择了这种方式,而不是对每个模型中的每个字段都明确地使用它。在每个表单类中添加额外的行没什么大不了的,但这只是让我感到困惑,我无法弄清楚。在django来源中进行的挖掘显示这可能是在做我不了解的事情:
django.forms.models
class ModelFormMetaclass(type):
def __new__(cls, name, bases, attrs):
formfield_callback = attrs.pop('formfield_callback', None)
但是我不知道
__init__
和__new__
如何相互缠结。在BaseForm中,我尝试在对super的调用之前和之后重写__init__
并设置formfield_callback,但是我猜测它必须位于args或kwargs中。 最佳答案
__new__在对象构造之前被调用。实际上,这是一个工厂方法,它返回一个新构造的对象的实例。
因此,ModelFormMetaclass中有3条关键行:
formfield_callback = attrs.pop('formfield_callback', None) #1
fields = fields_for_model(opts.model, opts.fields,
opts.exclude, opts.widgets, formfield_callback) #2
new_class.base_fields = fields #3
在该类中,我们将base_fields附加到表单。
现在让我们看一下ModelForm类:
class ModelForm(BaseModelForm):
__metaclass__ = ModelFormMetaclass
这意味着当我们创建ModelForm实例以更改 future 实例的结构时,将调用ModelFormMetaclass .__ new __(...)。而ModelFormMetaclass中的__new__( def __new __(cls,名称,基数,属性,atts))的attrs是ModelForm类的所有属性的决定。
因此,决定为我们的案例创建新的InheritedFormMetaclass(从ModelFormMetaclass继承)。不要忘记在InheritedFormMetaclass中调用父级的和新的。然后创建我们的BaseForm类,然后说:
__metaclass__ = InheritedFormMetaclass
在InheritedFormMetaclass的__new __(...)实现中,我们可以做所有我们想做的事情。
如果我的答案不够详细,请在评论的帮助下告诉我。
关于Django在ModelForms中继承formfield_callback的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7342925/