我是怎么做到使用django动态定义表单的

 我来答
从空去听8
2017-11-15 · TA获得超过7441个赞
知道大有可为答主
回答量:6907
采纳率:93%
帮助的人:5642万
展开全部

django中表单向导使用起来很简单的.

[python] view plain copy

  • from django.utils.translation import ugettext_lazy as _  

  • from django import forms  

  • from django.forms.formsets import BaseFormSet  

  • from django.forms.fields import FileField  

  • from django.forms.util import ValidationError  

  • from django.shortcuts import render_to_response  

  • from django.contrib.formtools.wizard import FormWizard  

  • from ddtcms.office.equipment.models import Equipment,Characteristic,CharacteristicValue  

  • class EquipmentForm(forms.ModelForm):  

  • class Meta:  

  • model = Equipment  

  • class CharacteristicValueForm(forms.Form):  

  • def clean(self):  

  • a=self.fields  

  • s=self.data  

  • self.cleaned_data = {}  

  • # 下面的这一段for 是从 django的forms.py中的 full_clean 中复制来的  

  • for name, field in self.fields.items():  

  • # value_from_datadict() gets the data from the data dictionaries.  

  • # Each widget type knows how to retrieve its own data, because some  

  • # widgets split data over several HTML fields.  

  • value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))  

  • try:  

  • if isinstance(field, FileField):  

  • initial = self.initial.get(name, field.initial)  

  • value = field.clean(value, initial)  

  • else:  

  • value = field.clean(value)  

  • self.cleaned_data[name] = value  

  • if hasattr(self, 'clean_%s' % name):  

  • value = getattr(self, 'clean_%s' % name)()  

  • self.cleaned_data[name] = value  

  • except ValidationError, e:  

  • self._errors[name] = self.error_class(e.messages)  

  • if name in self.cleaned_data:  

  • del self.cleaned_data[name]  

  • #cl=self.cleaned_data  

  • #debug()<<<调试用的,查看cl的值,主要是看self.cleaned_data的值,如果return了,就看不到了  

  • return self.cleaned_data  

  • class EquipmentCreateWizard(FormWizard):  

  • def done(self, request, form_list):  

  • return render_to_response('equipment/done.html',  

  • {  

  • 'form_data': [form.cleaned_data for form in form_list],  

  • })  

  • def get_form(self, step, data=None):  

  • "Helper method that returns the Form instance for the given step."  

  • form     = self.form_list[step](data, prefix=self.prefix_for_step(step), initial=self.initial.get(step, None))  

  • if step == 1:  

  • if data:  

  • cg       = data.get('0-category', 1)  

  • cs       = Characteristic.objects.all().filter(category__id=cg)  

  • for c in cs:  

  • form.fields['Characteristic-'+str(c.id)] = forms.CharField(label = c.name)  

  • g=form.fields  

  • #debug()  

  • return form  

  • # 从wizard.py中复制过来进行更改的.      

  • def render(self, form, request, step, context=None):  

  • "Renders the given Form object, returning an HttpResponse."  

  • old_data = request.POST  

  • prev_fields = []  

  • if old_data:  

  • hidden = forms.HiddenInput()  

  • # Collect all data from previous steps and render it as HTML hidden fields.  

  • for i in range(step):  

  • old_form = self.get_form(i, old_data)  

  • hash_name = 'hash_%s' % i  

  • prev_fields.extend([bf.as_hidden() for bf in old_form])  

  • prev_fields.append(hidden.render(hash_name, old_data.get(hash_name, self.security_hash(request, old_form))))  

  • if step == 1:  

  • cg       = old_data.get('0-category', 1)  

  • cs       = Characteristic.objects.all().filter(category__id=cg)  

  • for c in cs:  

  • form.fields['Characteristic-'+str(c.id)] = forms.CharField(label = c.name)  

  • g=form.fields  

  • #debug()  

  • if step == 2:  

  • debug()  

  • return super(EquipmentCreateWizard, self).render(form, request, step, context=None)  

  • def get_template(self, step):  

  • return 'equipment/wizard_%s.html' % step  

  • EquipmentCreateWizard其实也可以放在views.py中,而且我觉得更合理一点.
    在EquipmentCreateWizard 中,我试着修改过process_step 函数,但是得不到正确的结果,后来修改了get_form,都是想从django的formtools的wizard.py中复制过来再进行修改的.
    get_form的修改也没有得到正确的结果.后来就修改render函数,在第2步的时候,我将动态参数个数显示出来了.但是到最后结束done的环节,取得的formdata中,第二个form没有数据,就是一个空的{},
    于是我又重新修改get_form函数,无非就是判断是不是第二步,然后给第二个form动态添加几个field:

    [python] view plain copy

  • if step == 1:  

  • cg       = old_data.get('0-category', 1)  

  • cs       = Characteristic.objects.all().filter(category__id=cg)  

  • for c in cs:  

  • form.fields['Characteristic-'+str(c.id)] = forms.CharField(label = c.name)  

  • g=form.fields  

  • #debug()  

  • 这段代码在get_form和 render中都有,都是判断是不是第2步,然后就根据第1步中选择的设备的分类来查询到具体的分类,再根据分类来获取该种分类的设备有哪些参数,然后根据参数个数修改form的参数field的个数.
    'Characteristic-'+str(c.id)是用来以后保存数据的时候,split这个字符串,得到参数的id,并在参数值表中保存Characteristic-1,Characteristic-2...的value.

    g=form.fields
    #debug()

    用来断点查看参数field有多少个,是否修改成功.

    =========================

    [python] view plain copy

  • from django.conf.urls.defaults import *  

  • from ddtcms.office.equipment.forms import EquipmentForm,CharacteristicValueForm,EquipmentCreateWizard  

  • urlpatterns = patterns('ddtcms.office.equipment.views',  

  • url(r'^$', 'index', name="equipment_index"),   

  • url(r'^add/$', 'equipment_create', name="equipment_create"),  

  • url(r'^add-by-wizard/$',EquipmentCreateWizard([EquipmentForm, CharacteristicValueForm]), name="equipment_create_by_wizard"), )  

  • 以上代码,csdnbolg 自动过滤了 $符号,我加了上去,可能有不对的地方.  


  • ==========================
    wizard_0.html

    [html] view plain copy

  • {% block content %}  

  • <h2>添加/修改设备向导</h2>  

  • <p>第 {{ step }} 步, 共 {{ step_count }} 步.</p>  

  • <p>填写设备基本情况</p>  

  • <form method="POST" action="">{% csrf_token %}  

  • <table>  

  • {{ form }}  

  • </table>  

  • <input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />  

  • {{ previous_fields|safe }}  

  • <input type="submit" value="Submit" />  

  • </form>  

  • {% endblock %}  

  • ===================
    wizard_1.html

    [html] view plain copy

  • {% block content %}  

  • <h2>添加/修改设备向导</h2>  

  • <p>第 {{ step }} 步, 共 {{ step_count }} 步.</p>  

  • <p>填写设备参数, 如果没有要填写的内容, 请直接点击确定.</p>  

  • <form method="POST" action="">{% csrf_token %}  

  • <table>  

  • {{ form }}  

  • </table>  

  • <input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />  

  • {{ previous_fields|safe }}  

  • <input type="submit" value="Submit" />  

  • </form>  

  • {% endblock %}  

  • ====================
    done.html

    [html] view plain copy

  • {% block content %}  

  • <h2>添加/修改设备向导</h2>  

  • <p>您已经成功添加了一个设备.</p>  

  • {{form_data}}  

  • {% endblock %}  


  • ============

    还可以用另外的form来实现formwizard,就是第一个form1,主要用来让用户选择设备的分类,form2就根据前面的来动态生成参数的表单.原理是一样的.

    还有就是写2个view来模拟formwizard,第一个view增加一个设备,第二个view带设备id这个参数即可,可以很有效的增加设备的参数.

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式