Django modelForm更新某些字段

时间:2016-04-29 13:28:03

标签: django django-forms django-views

我有一个' 农场'模型和相应的ModelForm如下:

class FarmForm(ModelForm):
    class Meta:
        model = Farm
        fields = ['farm_name','address','farm_size', 'latitude', 'longitude']

我可以通过我的客户端应用程序保存新的 Farm 对象(它要求我填写我的ModelForm中提到的所有字段)。

我希望有另一个视图,我可以在其中更新现有的 Farm ,用户可以在其中插入/更新他/她想要更改的字段。我通过邮递员只传递一个字段值尝试了类似下面的内容,但它给了我Form_not_valid错误:

@api_view(['POST'])
def updateFarm(request, farmId):
   farm = Farm.objects.get(id=farmId)
   form = FarmForm(instance=farm, data=request.POST)
   if form.is_valid():
       farm = form.save()
       farm = Farm.objects.filter(id=farm.id)
       serializer = FarmSerializer(farm, many=True)
       return JSONResponse(serializer.data) 
       #return Response("Data saved")
   else:
       return Response("Form not valid, insert correct fields.")

如何构建我的视图,让用户只更新他认为相关的字段?我的网址:url(r'^farms/update/(?P<farmId>\d\d)/$', views.updateFarm),

1 个答案:

答案 0 :(得分:0)

您可以为模型中的每个字段生成一个布尔隐藏的表单字段,该字段在修改字段时设置。例如name输入:

<input id="id_name" maxlength="100" name="name" type="text">

后面会跟一个name__specified隐藏输入:

<input id="id_name__specified" name="name__specified" type="hidden">

您可以使用一些j跟踪字段name的更改(使用普通js或jquery非常容易),并相应地将name__specified更新为true / false。

为了自动执行此操作并能够重复使用它,您可以在基本表单类中对其进行抽象,并使表单保持简单:

class BaseForm(forms.ModelForm):
    suffix = '__specified'

    def __init__(self, **kwargs):
        super(BaseForm, self).__init__(**kwargs)

        fields = list(self.fields)
        for f in fields:
            # Set the field default value from the instance
            self.fields[f].widget.attrs['default'] = getattr(self.instance, f)

            # JS tracking field changes
            js = """
            document.getElementById("id_%s").value =
            this.value != this.getAttribute("default");
            """ % (f + self.suffix)
            self.fields[f].widget.attrs['onchange'] = js

            self.fields[f + self.suffix] = forms.BooleanField(
                widget=forms.HiddenInput(),
                required=False
            )

    def clean(self):
        data = super(BaseForm, self).clean()

        flags = [f for f in self.fields if self.suffix in f]
        for x in flags:
            specified = data.get(x, False)

            if not specified:
                field = x[:-len(self.suffix)]

                # If not specified grab it's current value from the instance
                data[field] = getattr(self.instance, field)

                # If the form validation complains that it's missing
                # clear the error since we are not changing it's value
                if field in self.errors:
                    del self.errors[field]

        return data

所以修改后的表格:

class FarmForm(BaseForm):
    class Meta:
        model = Farm
        fields = ['farm_name','address','farm_size', 'latitude', 'longitude']

注意,您应该在GET函数中实例化表单时传递实例,或者只是从UpdateView继承您的视图,以便自动处理:

class MyView(UpdateView):
    template_name = 'my_template.html'
    form_class = FarmForm
    queryset = Farm.objects.all() 

现在你可以进行部分更新了!