表单向导初始数据进行编辑,无法在Django中正确加载? [英] form wizard initial data for edit not loading properly in Django?

查看:125
本文介绍了表单向导初始数据进行编辑,无法在Django中正确加载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个单一模型的三页表单。我可以先保存模型,但是当我想编辑模型时,只有第一个表单显示初始值,后续表单不显示初始数据。但是当我从视图打印 initial_dict 时,我可以正确看到所有的初始视图。我遵循了博客表单向导。



这是我的 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 ,SecondForm,ThirdForm]),name ='wizards'),
url(r'^ edit /(?P< id> \d +)/ $','formwizard.views.edit_wizard',name = edit_wizard'),

forms.py:

  class FirstForm(forms.Form):
id = f orms.IntegerField(widget = forms.HiddenInput,required = False)
price = forms.DecimalField(max_digits = 8,decimal_places = 2)
#添加要包含在窗体$中的所有字段b
$ b class SecondForm(forms.Form):
image = forms.ImageField(required = False)

class ThirdForm(forms.Form):
description = forms.CharField(widget = forms.Textarea)

views.py:

 类MyWizard(SessionWizardView):
template_name =wizard_form.html
file_storage = FileSystemStorage(location = os.path.join (settings.MEDIA_ROOT))
#如果您正在上传文件,您需要设置FileSystemStorage
def done(self,form_list,** kwargs):
for form in form_list:
打印form.initial
如果不是self.request.user.is_authenticated():
raise Http404
id = form_list [0] .cleaned_data ['id']
try:
ite m = Item.objects.get(pk = id)
##################### SAVING ITEM ########## #############
item.save()
打印项
实例=项
除外:
项=无
instance = None
如果item和item.user!= self.request.user:
打印即将提高404
raise Http404
如果不是项目:
instance = Item()
form_list中的表单:
用于字段,在form.cleaned_data.iteritems()中的值:
setattr(实例,字段,值)
实例.user = self.request.user
instance.save()
返回render_to_response('wizard-done.html',{
'form_data':[form.cleaned_data for form in form_list] ,})


def edit_wizard(request,id):
#get对象
item = get_object_or_404(Item,pk = id)
#make确保该项目属于用户
如果item.user!= request.user:
raise HttpResponseForbidden()
else:
#get要包含的初始数据
initial = {'0':{'id':item.id,
'price' :item.price,
#make确保您列出您的窗体定义中的每个字段,以便稍后在initial_dict
}中包含它,
'1':{'image':item.image ,
},
'2':{'description':item.description,
},
}
打印初始
form = MyWizard.as_view ([FirstForm,SecondForm,ThirdForm],initial_dict = initial)
return form(context = RequestContext(request),request = request)

模板:

  HTML> 
< body>
< h2>联系我们< / h2> {{wizard.steps.count}}< / p>的步骤{{wizard.steps.step1}}
< p>
{%表单中的字段%}
{{field.error}}
{%endfor%}

< form action = {%url'向导'%} method =postenctype =multipart / form-data> {%csrf_token%}
< table>
{{wizard.management_form}}
{%如果wizard.form.forms%}
{{wizard.form.management_form}}
{%for wizard.form .forms%}
{{form}}
{%endfor%}
{%else%}
{{wizard.form}}
{%endif% }
< / table>
{%如果wizard.steps.prev%}
< button name =wizard_goto_steptype =submitvalue ={{wizard.steps.first}}>第一步 < /按钮>
< button name =wizard_goto_steptype =submitvalue ={{wizard.steps.prev}}>prev step< / button>
{%endif%}


< input type =submitvalue =提交/>

< / form>

< / body>
< / html>

编辑:
一个这个我注意到的是:
在编辑模式,即当我在以下url: http://127.0.0.1:8000/wizard/edit/1/
它显示第一个表单数据正确,当我点击提交时,它不会让我进入编辑模式的第二步,即URL更改为 http://127.0.0.1:8000/wizard/create/



如果点击编辑网址上的提交(如 /向导/编辑/ 1 )在第一步中,保持相同的url,则表单将在下一步中获取其初始数据。但是我无法弄清楚如何将url更改为 / wizard / create

解决方案

错误看起来很简单。在您的模板中,表单动作具有向导 url,这是创建视图的url。因此,当提交表单时,它将转到 / wizard / create



为了能够使用模板视图,您可以从表单标签中删除操作属性。该表单将提交给当前可以创建或编辑的网址。



所以更改您的模板以具有表单标签为

 < form method =postenctype =multipart / form-data> 






编辑:保存项目



将您的视图更新为:

  def done(self,form_list,** kwargs) :
form_list中的表单
print form.initial
如果不是self.request.user.is_authenticated():
raise Http404
id = form_list [0] .cleaned_data ['id']
try:
item = Item.objects.get(pk = id)
打印项
instance = item
except:
item = None
instance = None
如果item和item.user!= self.request.user:
打印即将提高404
raise Http404
如果不是项目:
instance = Item()

#如果
为form_list中的表单,则为#b $ b:
为field,value为form.cleaned_data。 iteritems():
setattr(in立场,字段,值)
instance.user = self.request.user
instance.save()

返回render_to_response('wizard-done.html',{
'form_data':[form.cleaned_data for form in form_list],})


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.

Here is my 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)

template:

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

EDIT: 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/.

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

解决方案

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.

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.

So change your template to have form tag as

<form method="post" enctype="multipart/form-data">


EDIT: To save item

Update your view as:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆