2016-04-29 105 views
1

我有一个“农场”模型和相应的ModelForm如下:的Django的ModelForm更新某些领域

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

我可以节省通过我的客户端应用程序新农场对象(它要求我填写在我的ModelForm中提到的所有领域)。

我想有另一种观点认为在那里我可以更新现有农场,用户可以或许插入/更新只有他/她想要改变的字段。我想是这样仅通过邮路的字段值之一以下,但它给了我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),

+0

您想调用form is_valid,但您的表单将如何知道用户想要更改哪些字段并仅验证这些字段? – fips

回答

0

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

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

之后,将一个name__specified隐藏输入:

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

您跟踪更改到现场name一些JS(很容易与普通的JS或jQuery的),并相应更新name__specified为真/假。

为了自动做到这一点,并能够重新使用它,你可以抽象此碱形式类,并保持你的表:

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() 

现在你可以做部分更新!