2016-04-29 12 views
1

Ich habe eine ‚Farm‘ -Modell und eine entsprechende Modelform wie folgt:Django Modelform Update bestimmte Felder

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

ich ein neues Farm Objekt durch meine Client-Anwendung speichern kann (es erfordert, dass ich füllen in allen in meiner ModelForm genannten Bereichen).

Ich möchte eine andere Ansicht haben, in der ich eine vorhandene Farm aktualisieren kann, wo der Benutzer vielleicht nur die Felder einfügen/aktualisieren kann, die er/sie ändern möchte. Ich habe versucht, so etwas wie folgende von nur einer der Feldwerte durch Postbote vorbei, aber es gibt mir Form_not_valid Fehler:

@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.") 

Wie kann ich meine Ansicht erstellen, die nur Benutzer-Update lassen diese Felder denkt er relevant sind? Meine URL: url(r'^farms/update/(?P<farmId>\d\d)/$', views.updateFarm),

+0

Sie möchten das Formular is_valid aufrufen, aber wie wird Ihr Formular wissen, welche Felder der Benutzer ändern möchte und nur diese validieren? – fips

Antwort

0

Sie können ein boolesches ausgeblendetes Formularfeld für jedes Feld in Ihrem Modell generieren, das beim Ändern eines Felds festgelegt wird. Zum Beispiel name Eingang:

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

werden von einem name__specified versteckten Eingang folgen:

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

Sie Änderungen verfolgen name mit einigen js (sehr leicht mit einfachen js oder jquery) Feld und aktualisieren name__specified entsprechend zu wahr/falsch.

Um dies automatisch zu tun und in der Lage sein, es wieder zu verwenden, können Sie abstrakt dies in einer Basisformularklasse und halten Sie Ihre Form einfach:

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 

So Ihre abgewandelter Form:

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

Hinweis, sollten Sie die Instanz übergeben, wenn ein Formular in Ihrer Funktion GET oder einfach erben Ihre Ansicht von UpdateView Instanziieren so wird das automatisch behandelt werden:

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

Jetzt können Sie Teilupdates machen!

Verwandte Themen