Django:使用自定义保存方法更新表单中的对象

Posted

技术标签:

【中文标题】Django:使用自定义保存方法更新表单中的对象【英文标题】:Django: Updating Object in Forms with Custom Save Method 【发布时间】:2013-10-07 19:36:49 【问题描述】:

这是this question 的延续,我在其中学习了如何覆盖多步表单向导的save 方法,以在不同的表单中以不同的方式保存表单字段。感谢@Yuji Tomita 的帮助,我想出了如何正确保存表格。然而,此时我不知道如何更新实例并将更改保存到对象。

我尝试按照我从@Yuji 那里学到的逻辑,但未能正确更新对象。

这就是我所在的地方:

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)

以下是我如何重写向导的 done 方法来保存实例:

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

我应该如何更改我的save 方法,以便正确更新thing 实例?感谢您的想法!


编辑:添加编辑对象的视图:

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)

【问题讨论】:

在这一切之后你会运行 instance.save() 吗? 感谢您的评论@mariodev。我在表单向导的 done 方法中运行 instance.save()。我在编辑中包含了上面的信息。感谢您提供任何可以帮助我解决这个难题的想法! 【参考方案1】:

你看到了什么问题?获取错误或对象未保存?

可能done() 方法中的缩进不正确,因此它没有调用form.save()。应该是这样的:

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

【讨论】:

你说得对,这就是问题所在。我不知道为什么,但我不得不将第三种形式的保存方法更改为def save(self, thing): 而不是def save(self, instance): 我使用的其他两种形式def save(self, instance): 知道为什么吗?无论哪种方式都非常感谢您! @NickB,如果它的模型形式,那么它将具有instance 属性,这可能会导致混淆。但不确定是不是这样。

以上是关于Django:使用自定义保存方法更新表单中的对象的主要内容,如果未能解决你的问题,请参考以下文章

使用注册表单添加到自定义用户字段(django)

在 Django 中使用自定义外键字段保存表单中的数据

在 django 模型自定义 save() 方法中,你应该如何识别一个新对象?

自定义 Django 表单不保存

Django如何保存自定义表单集

如何使用django自定义表单保存多个到多个字段