Creation wizard initial data for editing not loaded correctly in Django?

I have a list of three pages coming out of one model. I could save the model first, but when I want to edit the model, only the first form shows the initial value, the subsequent forms do not show the original data. but when I print initial_dict from the views, I can see all the initial views correctly. I followed this blog in the 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 I noticed, this is the following: In edit mode, i.e. When I am at the following URL: http://127.0.0.1:8000/wizard/edit/1/ , it displays the data of the first form correctly, and when I click the "Submit" button, this does not lead me to step 2 of the editing mode, those. The URL changes to http://127.0.0.1:8000/wizard/create/ .

If by clicking submit on the editing URL (for example, /wizard/edit/1 ) the same URL is supported in the first step, the form will receive its initial data in the next step. but i can't figure out how to avoid changing the url to /wizard/create

0
source share
1 answer

The error seems trivial. In your template, the form action has a wizards url, which is the url for creating the view. Therefore, when the form is submitted, it goes to /wizard/create .

To use a template for both views, you can remove the action attribute from the form tag. The form will be sent to the current URL, which you can create or edit.

So modify the template to have a form tag like

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

EDIT: save item

Refresh 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], }) 
+1
source

All Articles