form wizard initial data for edit not loading properly in Django?

☆樱花仙子☆ 提交于 2019-12-20 07:20:03

问题


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


回答1:


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], })


来源:https://stackoverflow.com/questions/24173367/form-wizard-initial-data-for-edit-not-loading-properly-in-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!