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

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

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:

1

2

3

4

5

6

7

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有多少个,是否修改成功.

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

1

2

3

4

5

6

7

8

9

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

{% 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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

{% 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

1

2

3

4

5

6

7

8

{% block content %}

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

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

{{form_data}}

{% endblock %}

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

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

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

有两种方法。

一、自己手动写 html 模板中的 <form ...></form> 

在views 中,将所需要的数据传递过去,比如 names_list = [1, 2, 3, 4]

在 html 中

<select>

  {% for x in name_list %}

      <option value ="{{ x }}">{{ x }}</option>

  {% endfor %}

</select>

二、使用 Form 自动生成表单

这就需要在 views 中 动态初始化表单

具体的内容自己查 相应版本的 django文档去

内容在“Forms”中。

最后给你个建议吧。好好看文档去,在这提问等答案的功夫,不知能看多少文档。

学习从来都是自己的事情,多看多读多思考,实在不会再去问。

你还是没做过类似的东西吧。方法有很多种,最简单的是设置id,每一行的设置为str(index+1)类似,提交方法写在js,js查明该行的id就知道是那一行了,你弄个这么大范围的form岂不是把所有的input都提交了


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11674922.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存