2013-02-20 15 views
9

utilizzando Django restDjango RIPOSO: oggetto nidificato add on creare (POST) non solo aggiornare (PUT)

Qui di seguito è come ho avuto il mio serializer.py.

class ProfileSerializer(serializers.ModelSerializer): 


    class Meta: 
     model = Profile 
     fields = ('id', 'name', 'active', 'type') 

tipo è un flatview

Ho poi cambiato così 'tipo' è stato nidificato per ogni profilo come questo ...

class TypeSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Type 
     fields = ('id', 'name', 'active') 

class ProfileSerializer(serializers.ModelSerializer): 

    type = TypeSerializer() 

    class Meta: 
     model = Profile 
     fields = ('id', 'name', 'active', 'type'') 

ora questo funziona perfettamente, ma posso ora aggiorna solo 'tipo' quando nel dettaglio del profilo ora è di sola lettura.

Come è possibile aggiungere un tipo durante la creazione di un nuovo profilo e mantenere comunque questa vista nidificata?

Spero di averlo spiegato chiaramente.

UPDATE:

Ok, ho appena letto questo:

Nota: serializzatori nidificati sono adatti solo per sola lettura rappresentazioni, in quanto vi sono casi in cui avrebbero dovuto ambiguo o comportamento non ovvio se utilizzato durante l'aggiornamento delle istanze. Per le rappresentazioni di lettura-scrittura è necessario utilizzare sempre una rappresentazione piatta, utilizzando una delle sottoclassi RelatedField.

Quindi ha senso. Così ho cambiato ....

type = serializers.PrimaryKeyRelatedField() 

che lo mette di nuovo in POST e il lavoro, ma è un peccato, non posso rappresentare 'tipo' con ID e il nome in modo che rende più senso per il utente finale?

risposta

12

Supporto completo di serializzatori annidati scrivibile è un work in progress, ma nel frattempo una soluzione è eseguire l'override del metodo create nella vista in ogni caso:

class FooListCreateView(ListCreateAPIView): 
    model = Foo 
    serializer_class = FooSerializer 

    def create(self, request, *args, **kwargs): 
     data=request.DATA 

     f = Foo.objects.create() 

     # ... create nested objects from request data ... 

     # ... 
     return Response(serializer.data, 
         status=status.HTTP_201_CREATED, 
         headers=headers) 

Probabilmente non è l'ideale, ma funziona per me finché non arriva la giusta via.

+0

ho scoperto che SlugRelatedField mi permette di cambiare la società dal id per qualcosa di significativo come il titolo o il nome del campo, ma questo è usando un campo piatto non annidato. Ritenterò con nidificato e vedrò se l'override potrebbe funzionare. – jason

+0

Puoi spiegare, come possiamo convalidare altri campi qui? – CrazyGeek

6

Ho avuto lo stesso problema in django-riposo-quadro, e ho creato una visualizzazione per fare questo reale veloce, lo si può trovare in questo succo: https://gist.github.com/edulix/5311365

Utilizzo base di CRUDManyToManyView è il seguente :

views.py

from models import Project 
from serializers import TaskSerializer 
from lib.crudmanytomanyview import CRUDManyToManyView 

class ProjectTasks(CRUDManyToManyView): 
    model = Project 
    field_name = 'tasks' 
    serializer_class = TaskSerializer 

urls.py

from django.conf.urls import patterns, url 
import views 

urlpatterns = patterns(
'', 
    url(r'^projects/(?P<pk>[0-9]+)/tasks/((?P<field_pk>[0-9]+)/)?$', 
     views.ProjectTasks.as_view()), 
) 

serializzatori.py

from rest_framework import serializers 
from models import Task 

class TaskSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Task 
     fields = ('id', 'name') 

models.py

from django.db import models 

class Task(models.Model): 
    name = models.CharField(max_length=140, blank=False, null=False) 

class Project(models.Model): 
    name = models.CharField(max_length=140, blank=False, null=False) 
    tasks = models.ManyToManyField(Task, related_name='projects') 

Poi si può fare cose come:

  • GET progetti/12/compiti/ elencherà le attività del progetto
  • Progetti POST/12/attività/1/ che aggiungerà il compito 1 alla lista dei progetti 12 compiti (task 1 deve essere già presente) progetti
  • cancellare/12/attività/1/ che rimuoverà il compito 1 dalla lista dei progetti 12 compiti
4

Questo è ora supportato (sto usando la versione 2.3.6 ma potrebbe essere introdotto in precedenza). Si può usare nel serializzatore direcly in questo modo:

class SongSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Song 

class AlbumSerializer(serializers.ModelSerializer): 
    songs = SongSerializer(many=True) 

    class Meta: 
     model = Album 

Speranza che aiuta :)

+1

Questo frammento di codice è corretto? Da dove proviene ImageFeatureSerializer? E il modello di SongSerializer è un altro SongSerializer? – user798719

+0

Scusate, stavo convertendo un po 'del mio codice per adattarlo all'esempio precedente, ed è stato un po' di fretta. Questo dovrebbe funzionare. Grazie! –

+0

@RaresMusina Che aspetto avrebbe una richiesta POST adesso? –

Problemi correlati