我现在才使用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/

10-12 18:34