2015-01-16 18 views
19

Ho un modello "MyModel" con molti campi e vorrei aggiornare lo stato di un campo usando il metodo PATCH. Sto usando le viste basate sulla classe. C'è un modo per implementare PATCH?Come PATCHare un singolo campo usando Django Rest Framework?

+0

puoi semplicemente controllare 'request.method == 'PATCH'' nel tuo codice di visualizzazione e poi fare quello che vuoi. –

+0

Mi piacerebbe sapere come gestirlo nella classe serializzatore. – pnhegde

+0

La classe serializzatore non è il luogo che deve sapere qualcosa sul metodo di richiesta. Quindi ti consiglio di controllare le classi di visualizzazione (come 'APIView'), non i serializzatori –

risposta

17

I serializzatori consentono partial updates by specifying partial=True durante l'inizializzazione del serialzer. Questo è il modo PATCH requests are handled per impostazione predefinita in the generic views.

serializer = CommentSerializer(comment, data=request.data, partial=True) 

Questo vi permetterà di aggiornare i singoli campi in un serializzatore, o tutti i campi, se si desidera, senza alcuna delle restrizioni di PUT richiesta standard.

+12

Dove va esattamente? –

+1

Buona domanda @ScottSmith. Sembra che la documentazione e altre fonti citino solo questo one-liner come soluzione per eseguire aggiornamenti parziali. Ma non va bene se non sa dove mettere questa riga di codice. – JayGee

+1

"dove va?" dipende da come sono scritte le tue opinioni. Questa risposta presuppone che tu non stia utilizzando viste generiche, ma che tu stia ruotando da solo. –

3

Sembra supportato immediatamente. Nell'API del browser, vai a una pagina dei dettagli del modello, in basso accanto alla scheda HTML Form fai clic su Raw data, elimina tutto dalla stringa JSON tranne il campo ID e il campo che desideri modificare e fai clic su PATCH. Viene eseguito un aggiornamento parziale PATCH.

Sto usando djangorestframework==3.2.4 e non ho dovuto fare nulla per i miei ViewSet e serializzatori per abilitare questo.

In questo exampe stiamo aggiornando il campo bool status_field del modello e sto usando jquery 2.2.1. Aggiungere il seguente alla <head>:

<script src="{% static 'my_app/jquery.min.js' %}"></script> 
<script> 
$(document).ready(function(){ 
    var chk_status_field = $('#status_field'); 
    chk_status_field.click(function(){ 
     $.ajax({url: "{% url 'model-detail' your_rendering_context.id %}", 
      type: 'PATCH', timeout: 3000, data: { status_field: this.checked } 
     }) 
     .fail(function(){ 
      alert('Error updating this model instance.'); 
      chk_status_field.prop('checked', !chk_status_field.prop('checked')); 
     }); 
    }); 
}); 
</script> 

Poi, in un <form>:

<input type="checkbox" id="status_field" {% if your_rendering_context.status_field %} 
    checked {% endif %} > 

ho scelto di consentire la casella di controllo per cambiare, poi ritornerà in caso di guasto. Ma è possibile sostituire click con mousedown per aggiornare solo il valore della casella di controllo una volta che la chiamata AJAX è riuscita. Penso che questo porterà le persone a fare ripetutamente clic sulla casella di controllo per connessioni lente.

6

Come Kevin Brown dichiarato che è possibile utilizzare il partial=True, che chefarov chiarificato bene.

vorrei solo per correggerle e dire che è possibile utilizzare farmaci generici liberamente, a seconda del metodo HTTP che si sta utilizzando:

  • Se si utilizza il metodo HTTP PATCH come richiesto, si ottiene fuori la scatola. Si può vedere UpdateModelMixin codice per partial_update:

    def partial_update(self, request, *args, **kwargs): 
        kwargs['partial'] = True 
        return self.update(request, *args, **kwargs) 
    
  • Per qualsiasi metodo HTTP diverso da PATCH, questo può essere ottenuto solo l'override del metodo get_serializer come segue:

    def get_serializer(self, *args, **kwargs): 
        kwargs['partial'] = True 
        return super(YOUR_CLASS, self).get_serializer(*args, **kwargs) 
    

Questo creerà il serializzatore è parziale e il resto dei generici funzionerà come un incantesimo senza alcun intervento manuale nel meccanismo update/partial_update.

Sotto il cofano

ho usato il generico: generics.UpdateAPIView che utilizza il UpdateModelMixin che ha questo codice:

def update(self, request, *args, **kwargs): 
    partial = kwargs.pop('partial', False) 
    instance = self.get_object() 
    serializer = self.get_serializer(instance, data=request.data, partial=partial) 
    … 

Quindi, se si ignora la funzione get_serializer, si può effettivamente ignorare il parziale argomento e costringerlo ad essere vero.

Si prega di notare che, se lo si vuole parziale solo per alcuni dei metodi HTTP, questo rende questo approccio più difficile.

Sto usando djangorestframework == 3.5.3

0

Ho lottato con questo per un po ', ma è un'implementazione molto semplice utilizzando le visualizzazioni generiche o una combinazione di punti di vista generici e mixins.

Nel caso di utilizzo di una vista update generico (generics.UpdateAPIView), basta usare il codice seguente, assicurandosi che il tipo di richiesta è PATCH:

class UpdateUser(generics.UpdateAPIView): 

    queryset = User.objects.all() 
    serializer_class = UserSerializer 

Non c'è niente altro da fare!

Se stai usando un mixin aggiornamento (mixins.UpdateModelMixin) in combinazione con una vista generica (generics.GenericAPIView), utilizzare il codice seguente, assicurandosi che il tipo di richiesta è PATCH:

class ActivateUser(mixins.UpdateModelMixin, generics.GenericAPIView): 

    serializer_class = UserSerializer 
    model = User 
    lookup_field = 'email' 

    def get_queryset(self): 
     queryset = self.model.objects.filter(active=False) 
     return queryset 

    def patch(self, request, *args, **kwargs): 
     return self.partial_update(request, *args, **kwargs) 

Il il secondo esempio è più complesso e mostra come sovrascrivere il campo di ricerca e il queryset, ma il codice a cui prestare attenzione è la funzione patch.

Problemi correlati