2

在 James Bennett 的文章“So you want a dynamic form”(2008 年 11 月 9 日)中,他写道,要创建动态表单,您可以执行以下操作:

def make_contact_form(user):
    fields = { 'name': forms.CharField(max_length=50),
               'email': forms.EmailField(),
               'message': forms.CharField(widget=forms.Textarea) }
    if not user.is_authenticated():
        fields['captcha'] = CaptchaField()
    return type('ContactForm', (forms.BaseForm,), { 'base_fields': fields })

但是你会如何做同样的事情forms.ModelForm呢?

到目前为止,我只是在做这样的事情(我不知道如何使用type内部类'Meta')

def make_order_edit_form(include_fields):
    class _OrderEditForm(forms.ModelForm):
        if 'fa_date' in include_fields:
            fa_date = CustomDateTimeField(label="first appointment time")

        class Meta:
            model = Order
            fields = include_fields
            widgets = custom_widgets

    return _OrderEditForm

include_fields我要显示的字段元组在哪里。

但是,即使我写了正确的make_order_edit_form,我该如何使用它views.py呢?具体来说,如何将 POST 请求和订单实例都传递给它?通常我会做类似的事情

order = Order.objects.get(pk=pk)

order_form = OrderEditForm(data=request.POST, instance=order)

奖金问题:

为什么 Bennett 创造了ContactFormout offorms.BaseForm而不是forms.Form?(我假设这就是为什么也调用这些字段的原因base_fields。)

4

1 回答 1

3

make_order_edit_form返回一个ModelForm类,因此你可以

form_cls = make_order_edit_form(fields)
order_form = form_cls(request.POST, instance=order)

对于奖金问题,请检查Form代码:

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.
    __metaclass__ = DeclarativeFieldsMetaclass

有一个自定义的Form元类DeclarativeFieldsMetaclass,它自动收集用声明性语法编写的表单字段,如果你使用Formin type(),它看起来像(以 Bennett 的例子)

type('ContactForm', (forms.Form,), {
    'name': forms.CharField(max_length=50),
    'email': forms.EmailField(),
    'message': forms.CharField(widget=forms.Textarea)}
# instead of
type('ContactForm', (forms.BaseForm,), { 'base_fields': fields })

更新

建立ModelForm使用type,没有太大的不同

def make_order_edit_form(include_fields):
    d = {}
    class Meta:
        model = Order
        fields = include_fields
        widgets = custom_widgets 
    d = {'Meta':Meta}
    if 'fa_date' in include_fields:
        d['fa_date'] = CustomDateTimeField(label="first appointment time")
    return type('OrderEditForm', (forms.ModelForm,), d)
于 2012-06-01T04:59:17.303 回答