2016-04-29 447 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() 

現在你可以做部分更新!