2013-02-20 4 views
9

Korzystanie Django restDjango REST: Zagnieżdżone dodać obiekt na tworzenie (POST) nie tylko aktualizować (PUT)

Poniżej jest jak miałem serializer.py.

class ProfileSerializer(serializers.ModelSerializer): 


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

Type jest flatview

I potem zmienił go tak 'typem' został zagnieżdżone dla każdego profilu jak to ...

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

teraz działa idealnie, ale mogę teraz tylko aktualizuj "typ", gdy w szczegółach profilu jest on teraz tylko do odczytu.

Jak mogę dodać typ podczas tworzenia nowego profilu i nadal zachować ten zagnieżdżony widok?

Mam nadzieję, że wyjaśnia to wyraźnie.

UPDATE:

Ok, po prostu przeczytać:

Uwaga: Zagnieżdżone serializers nadają się tylko do tylko do odczytu przedstawień, jak istnieją przypadki, w których miałyby one niejednoznaczne lub nieoczywiste zachowanie, jeśli jest używane podczas aktualizowania instancji. Do odczytu reprezentacje zawsze należy użyć płaskiego reprezentację, korzystając jedną z podklasy RelatedField.

Więc to ma sens. Więc zmieniłem go ....

type = serializers.PrimaryKeyRelatedField() 

To stawia go w post i pracy, ale to wstyd, nie mogę reprezentować „typ” z ID i nazwę, więc to sprawia, że ​​więcej sensu do użytkownik końcowy?

Odpowiedz

12

Pełna obsługa zapisywalnych zagnieżdżonych serializers jest work in progress, ale w tym czasie jednym z rozwiązań jest zastąpić metodę create zdaniem w każdym przypadku:

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) 

Prawdopodobnie nie jest idealny, ale to działa na mnie dopóki nie nadejdzie właściwa droga.

+0

stwierdziliśmy, że SlugRelatedField pozwalają mi teraz zmienić id do czegoś sensownego jak tytuł lub nazwę pola, ale to przy użyciu płaskiego pola nie zagnieżdżonego. Spróbuję ponownie z zagnieżdżeniem i zobaczę, czy operacja może zostać zastąpiona. – jason

+0

Czy możesz wyjaśnić, w jaki sposób możemy sprawdzić tutaj inne pola? – CrazyGeek

6

Miałem ten sam problem w Django-Rest-ram, i ja stworzyliśmy widok dla robią to bardzo szybko, można go znaleźć w tym GIST: https://gist.github.com/edulix/5311365

Podstawy używania CRUDManyToManyView jest następujący :

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

serializerów.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') 

Następnie można robić takie rzeczy jak:

  • GET projektów/12/zadań/ będzie lista zadań projektowych
  • Projekty POST/12/zadania/1/ który doda zadanie 1 na liście projektów 12 zadań (zadanie 1 musi już istnieć) projekty
  • usuwanie/12/zadania/1/ który usunie zadanie 1 z listy projekt 12 zadań
4

To jest teraz obsługiwane (korzystam z wersji 2.3.6, ale może zostać wprowadzone wcześniej). Można go używać w serializatora direcly tak:

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

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

    class Meta: 
     model = Album 

Nadzieja to pomaga :)

+1

Czy ten fragment kodu jest poprawny? Skąd pochodzi usługa ImageFeatureSerializer? A model SongSerializer to kolejny SongSerializer? – user798719

+0

Przepraszam, zamieniłem trochę mojego własnego kodu, aby pasowało do powyższego przykładu, i trochę się spieszyłem. To powinno działać. Dzięki! –

+0

@RaresMusina Jak wyglądałoby teraz żądanie POST? –

Powiązane problemy