用于编辑的表单向导初始数据未在 Django 中正确加载? [英] form wizard initial data for edit not loading properly in Django?
问题描述
我有一个来自单个模型的三页表单列表.我第一次可以保存模型,但是当我想编辑模型时,只有第一个表格显示初始值,后续表格不显示初始数据.但是当我从视图打印 initial_dict
时,我可以正确地看到所有初始视图.我在表单向导上关注了这个博客.
I have a three page form-list coming out of a single model. I could save the model first time, but when I want to edit the model, only the first form shows the initial value, subsequent forms does not show the initial data. but when I print the initial_dict
from views, I can see all the initial views correctly. I followed this blog on form wizard.
这是我的model.py:
class Item(models.Model):
user=models.ForeignKey(User)
price=models.DecimalField(max_digits=8,decimal_places=2)
image=models.ImageField(upload_to="assets/", blank=True)
description=models.TextField(blank=True)
def __unicode__(self):
return '%s-%s' %(self.user.username, self.price)
urls.py:
urlpatterns = patterns('',
url(r'^create/$', MyWizard.as_view([FirstForm, SecondForm, ThirdForm]), name='wizards'),
url(r'^edit/(?P<id>d+)/$', 'formwizard.views.edit_wizard', name='edit_wizard'),
)
forms.py:
class FirstForm(forms.Form):
id = forms.IntegerField(widget=forms.HiddenInput, required=False)
price = forms.DecimalField(max_digits=8, decimal_places=2)
#add all the fields that you want to include in the form
class SecondForm(forms.Form):
image = forms.ImageField(required=False)
class ThirdForm(forms.Form):
description = forms.CharField(widget=forms.Textarea)
views.py:
class MyWizard(SessionWizardView):
template_name = "wizard_form.html"
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT))
#if you are uploading files you need to set FileSystemStorage
def done(self, form_list, **kwargs):
for form in form_list:
print form.initial
if not self.request.user.is_authenticated():
raise Http404
id = form_list[0].cleaned_data['id']
try:
item = Item.objects.get(pk=id)
###################### SAVING ITEM #######################
item.save()
print item
instance = item
except:
item = None
instance = None
if item and item.user != self.request.user:
print "about to raise 404"
raise Http404
if not item:
instance = Item()
for form in form_list:
for field, value in form.cleaned_data.iteritems():
setattr(instance, field, value)
instance.user = self.request.user
instance.save()
return render_to_response('wizard-done.html', {
'form_data': [form.cleaned_data for form in form_list], })
def edit_wizard(request, id):
#get the object
item = get_object_or_404(Item, pk=id)
#make sure the item belongs to the user
if item.user != request.user:
raise HttpResponseForbidden()
else:
#get the initial data to include in the form
initial = {'0': {'id': item.id,
'price': item.price,
#make sure you list every field from your form definition here to include it later in the initial_dict
},
'1': {'image': item.image,
},
'2': {'description': item.description,
},
}
print initial
form = MyWizard.as_view([FirstForm, SecondForm, ThirdForm], initial_dict=initial)
return form(context=RequestContext(request), request=request)
模板:
<html>
<body>
<h2>Contact Us</h2>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action={% url 'wizards' %} method="post" enctype="multipart/form-data">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"first step"</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</button>
{% endif %}
<input type="submit" value="Submit" />
</form>
</body>
</html>
我注意到的一个是:在编辑模式下,即当我在以下网址时:http://127.0.0.1:8000/wizard/edit/1/
,它正确显示第一个表单数据,当我单击提交时,它不会将我带到编辑模式的第 2 步,即 URL 更改为 http://127.0.0.1:8000/wizard/create/代码>.
one this I noticed is the following:
On the edit mode, i.e, when I am at the following url : http://127.0.0.1:8000/wizard/edit/1/
,
it displays the first form data correctly, and when I click submit, it is not taking me to step-2 of edit mode, i.e the URL changes to http://127.0.0.1:8000/wizard/create/
.
如果在第一步单击编辑 url(如 /wizard/edit/1
)上的 submit
时,保持相同的 url,则表单将获得其初始数据在下一步.但我不知道如何避免 url 更改为 /wizard/create
If upon clicking submit
on edit url (like /wizard/edit/1
) in the first step, same url is maintained then the form would get its initial data in next step. but I cannot figure out how to avoid the url from changing to /wizard/create
推荐答案
该错误看起来微不足道.在您的模板中,表单操作具有 wizards
url,即 create 视图的 url.因此,当表单提交时,它会转到 /wizard/create
.
The error looks trivial. In your template the form action has wizards
url, which is url of create view. Hence when the form is submitted it goes to /wizard/create
.
为了能够在两个视图中使用模板,您可以从 form
标签中删除 action
属性.表单将提交到可以创建或编辑的当前 url.
To able to use the template for both views, you can remove the action
attribute from form
tag. The form will be submitted to current url which can be create or edit.
因此将您的模板更改为具有 form
标记为
So change your template to have form
tag as
<form method="post" enctype="multipart/form-data">
<小时>
保存项目
To save item
将您的视图更新为:
def done(self, form_list, **kwargs):
for form in form_list:
print form.initial
if not self.request.user.is_authenticated():
raise Http404
id = form_list[0].cleaned_data['id']
try:
item = Item.objects.get(pk=id)
print item
instance = item
except:
item = None
instance = None
if item and item.user != self.request.user:
print "about to raise 404"
raise Http404
if not item:
instance = Item()
#moved for out of if
for form in form_list:
for field, value in form.cleaned_data.iteritems():
setattr(instance, field, value)
instance.user = self.request.user
instance.save()
return render_to_response('wizard-done.html', {
'form_data': [form.cleaned_data for form in form_list], })
这篇关于用于编辑的表单向导初始数据未在 Django 中正确加载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!