动态地将表单字段添加到django表单

Alf*_*rez 7 python forms django

由于BD设计取决于值,数据存储在不同的单元格中,我必须动态添加表单字段.我在想这个:

class EditFlatForm(BaseModelForm):


    on_sale = forms.BooleanField(required=False)
    on_rent = forms.BooleanField(required=False)


    class Meta:

        model = Flat

        fields = ('title', 'flat_category', 'description')

        ...


    def __init__(self, *args, **kwargs):

        super(EditFlatForm, self).__init__(*args,**kwargs)


        flat_properties = FlatProperty.objects.all()

        for p in flat_properties:

            if p.type_value == 1:
                # Text
                setattr(self, p.title, forms.CharField(label=p.human_title, required=False))
            elif p.type_value == 2:
                # Number
                setattr(self, p.title, forms.IntegerField(label=p.human_title, required=False))
            else:
                # Boolean
                setattr(self, p.title, forms.BooleanField(label=p.human_title, required=False))
Run Code Online (Sandbox Code Playgroud)

但这些字段没有添加,我错过了什么?

Ser*_*eim 6

我建议使用即时创建表单type.因此,您需要创建一个函数,该函数将生成您希望在表单中包含的所有字段的列表,然后使用它们生成表单,如下所示:

def get_form_class():
    flat_properties = FlatProperty.objects.all()
    form_fields = {}
    for p in flat_properties:
        if p.type_value == 1:
        form_fields['field_{0}'.format(p.id)] = django.forms.CharField(...)
        elif p.type_value == 2:
            form_fields['field_{0}'.format(p.id)] = django.forms.IntegerField(...)
        else:
            form_fields['field_{0}'.format(p.id)] = django.forms.BooleanField(...)
    # ok now form_fields has all the fields for our form
    return type('DynamicForm', (django.forms.Form,), form_fields  )

现在,您可以get_form_class在任何想要使用表单的地方使用它

form_class = get_form_class()
form = form_class(request.GET) 
if form.is_valid() # etc 
Run Code Online (Sandbox Code Playgroud)

有关更多信息,您可以查看我使用django创建动态表单的帖子:http: //spapas.github.io/2013/12/24/django-dynamic-forms/

更新以解决OP的评论(但后来如何利用ModelForm提供的所有功能?):您可以从中继承您的动态表单ModelForm.或者,甚至更好,你可以创建一个类,是的后裔ModelForm,并定义了所有所需的方法和属性(如clean,__init__,Meta等).然后通过更改type调用来继承该类type('DynamicForm', (CustomForm,), form_fields )!


Mih*_*fir 5

假设这p.title是一个字符串变量,那么这应该有效:

if p.type_value == 1:
     # Text
     self.fields[p.title] = forms.CharField(label=p.human_title, required=False))
Run Code Online (Sandbox Code Playgroud)