为什么Django使用BaseForm?

时间:2010-07-04 23:43:20

标签: python django design-patterns

我想我终于想通了他们需要使用这个DeclarativeFieldsMetaclass(将类字段转换为实例变量并使用有序/排序的字典维护它们的顺序)。但是,我仍然不确定为什么他们选择使用BaseForm而不是直接在Form类中实现所有内容?

他们left a comment

class Form(BaseForm):
    "A collection of Fields, plus their associated data."
    # This is a separate class from BaseForm in order to abstract the way
    # self.fields is specified. This class (Form) is the one that does the
    # fancy metaclass stuff purely for the semantic sugar -- it allows one
    # to define a form using declarative syntax.
    # BaseForm itself has no way of designating self.fields.

但我真的不明白。 “为了抽象指定self.fields的方式” - 但Python在DeclarativeFieldsMetaclass.__new__之前调用Form.__init__,因此他们可以充分利用self.fields内的Form.__init__作为是;为什么他们需要额外的抽象层?

2 个答案:

答案 0 :(得分:2)

我认为理由是简单的,仅凭BaseForm,您无法使用decalrative语法定义字段,即

class MyForm(Form):
    field_xxx = form.TextField(...)
    field_nnn _ form.IntegerField(...)

对于这样的工作,应该有一个仅在Form中设置的元类DeclarativeFieldsMetaclass,他们这样做是因为

  

这是一个与BaseForm不同的类   为了抽象的方式,   self.fields是特定的

所以现在你可以编写WierdForm类,其中可以定义的字段可能是以某种奇怪的方式,例如将params传递给类对象,点是BaseForm中的所有API,Form类只提供一个易于定义的字段。

摘要:IMO django倾向于引入另一个层,以便在需要时可以实现不同类型的字段声明,至少它可以使表单的非核心功能保持独立。

答案 1 :(得分:0)

<强>来源:

class MetaForm(type):
    def __new__(cls, name, bases, attrs):
        print "%s: %s" % (name, attrs)
        return type.__new__(cls, name, bases, attrs)

class BaseForm(object):
    my_attr = 1
    def __init__(self):
        print "BaseForm.__init__"

class Form(BaseForm):
    __metaclass__ = MetaForm
    def __init__(self):
        print "Form.__init__"

class CustomForm(Form):
    my_field = 2
    def __init__(self):
        print "CustomForm.__init__"

f = CustomForm()

<强>输出:

Form: {'__module__': '__main__', '__metaclass__': <class '__main__.MetaForm'>, '__init__':<function __init__ at 0x0227E0F0>}
CustomForm: {'__module__': '__main__', 'my_field': 2, '__init__': <function __init__ at 0x0227E170>}
CustomForm.__init__

看起来MetaForm.__new__被调用两次。一次为Form,一次为CustomForm,但从不为BaseForm。通过使用干净(空)Form类,循环不会有任何无关的属性。这也意味着您可以在Fields中定义可用于内部使用的BaseForm,但避免渲染。