0

This is a continuation of this question, in which I learned how to over-ride the save method of a multi-step formwizard to save form fields differently in different forms. Thanks to @Yuji Tomita's help, I figured out how to save the forms correctly. At this point, however, I am lost on how to update the instance and save changes to the object.

I have tried to follow the logic I learned from @Yuji, but have not been able to properly update the object.

This is where I am:

class StepOneForm(forms.Form):
     ...
     def save(self, thing):
        for field, value in self.cleaned_data.items():
            setattr(thing, field, value)

class StepTwoForm(forms.Form):
     ...
     def save(self, thing):
        for field, value in self.cleaned_data.items():
            setattr(thing, field, value)

class StepThreeForm(forms.Form):
     ...
     def save(self, thing):
         thing.point = Point.objects.get_or_create(latitude=self.cleaned_data.get('latitude'), longitude=self.cleaned_data.get('longitude'))[0]
         for field, value in self.cleaned_data.items():
             setattr(thing, field, value)

Here is how I have over-written the wizard's done method to save the instances:

class MyWizard(SessionWizardView):
    file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT))
    def done(self, form_list, **kwargs):
        id = form_list[0].cleaned_data['id']
        try:
            thing = Thing.objects.get(pk=id)
            instance = thing
        except:
            thing = None
            instance = None
        if thing and thing.user != self.request.user:
            raise HttpResponseForbidden()
        if not thing:
            instance = Thing()
            for form in form_list:
                form.save(instance)
            instance.user = self.request.user
            instance.save()
        return render_to_response('wizard-done.html', {
                'form_data': [form.cleaned_data for form in form_list],})

How should I change my save method so that I can properly update the thing instance? Thanks for your ideas!


EDIT: Adding the view that edits the object:

def edit_wizard(request, id):
    thing = get_object_or_404(Thing, pk=id)
    if thing.user != request.user:
        raise HttpResponseForbidden()
    else:
        initial = {'0': {'id': thing.id,
                       'year': thing.year,
                       'color': thing.color,
                       ... #listing form fields individually to populate the initial_dict for the instance
                       },
                   '1': {image': thing.main_image,
                       ...
                       },
                   '2': {description': thing.additional_description,
                       'latitude': thing.point.latitude,  #thing has a foreign key to point that records lat and lon
                       'longitude': thing.point.longitude,
                       },
                    }

        form = MyWizard.as_view([StepOneForm, StepTwoForm, StepThreeForm], initial_dict=initial)
        return form(context=RequestContext(request), request=request)
2
  • Do you run instance.save() after all this? Commented Oct 8, 2013 at 5:59
  • Thanks for your comment @mariodev. I am running instance.save() in the done method of my formwizard. I have included that information above in an edit. Thanks for any ideas that may help me figure out this difficult problem! Commented Oct 8, 2013 at 18:06

1 Answer 1

1
+50

What is problem that you are seeing? Get error or object is not saved?

Probably the indentation in your done() method is not correct, so its not calling the form.save(). It should be like :

class MyWizard(SessionWizardView):
    file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT))
    def done(self, form_list, **kwargs):
        ... 
        #existing code

        if not thing:
            instance = Thing()

        #this is moved out of if
        for form in form_list:
            form.save(instance)

        instance.user = self.request.user
        instance.save()
        return render_to_response('wizard-done.html', {
                'form_data': [form.cleaned_data for form in form_list],})
Sign up to request clarification or add additional context in comments.

2 Comments

You are right that was the problem. I'm not sure why but I had to change the save method on only the third form to def save(self, thing): instead of def save(self, instance): The other two forms I used def save(self, instance): Any idea why? Either way thank you very much!
@NickB, if its model form, then it would have instance attribute which might be causing the confusion. But not sure thats the case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.