2013-02-20 3 views
9

à l'aide Django restDjango REST: objet imbriqué ajouter à créer (POST) non seulement la mise à jour (PUT)

est ci-dessous comment j'avais mon serializer.py.

class ProfileSerializer(serializers.ModelSerializer): 


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

type est un flatview

je puis changé si 'type' a été imbriqué pour chaque profil comme celui-ci ...

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

maintenant cela fonctionne parfaitement, mais je peux maintenant seulement mettre à jour 'type' quand dans le détail du profil, il est maintenant en lecture seule.

Comment puis-je ajouter le type lors de la création d'un nouveau profil et de toujours garder ce point de vue imbriquée?

J'espère que je l'ai expliqué clairement.

MISE À JOUR:

Ok, je viens de lire ceci:

Note: emboîtées serializers ne conviennent que pour en lecture seule représentations, comme il y a des cas où ils auraient ambiguës ou comportement non évident si utilisé lors de la mise à jour des instances. Pour les représentations en lecture-écriture , vous devez toujours utiliser une représentation plate, en utilisant l'une des sous-classes RelatedField.

Donc cela fait sens. Alors je l'ai changé ....

type = serializers.PrimaryKeyRelatedField() 

Qu'il remet dans le poste et le travail, mais il est dommage, je peux pas représenter « type » avec ID et le nom de sorte qu'il est plus logique de la utilisateur final?

Répondre

12

Support complet des serializers imbriquées inscriptibles est un work in progress, mais dans le même temps une solution consiste à remplacer la méthode create dans la vue dans chaque cas:

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) 

Probablement pas idéal, mais ça fonctionne pour moi jusqu'à ce que la bonne voie arrive.

+0

Je trouve que SlugRelatedField me permet de changer maintenant de l'identifiant à quelque chose de significatif comme le titre ou le nom du champ mais c'est en utilisant un flatfield non imbriqué. Je vais réessayer avec imbriqué et voir si le remplacement pourrait fonctionner. – jason

+0

Pouvez-vous expliquer, comment pouvons-nous valider d'autres champs ici? – CrazyGeek

6

J'ai eu le même problème dans django-repos-cadre, et je l'ai créé une vue pour faire ce réel rapide, vous pouvez le trouver dans ce point essentiel: https://gist.github.com/edulix/5311365

Utilisation de base de CRUDManyToManyView est le suivant :

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

sérialiseurs.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') 

Ensuite, vous pouvez faire des choses comme:

  • projets GET/12/tâches/ liste les tâches du projet
  • Projets POST/12/Tâches/1/ qui ajoutera la tâche 1 à la liste des projets 12 tâches (tâche 1 doit déjà exister)
  • projets SUPPRIMER/12/tâches/1/ qui supprimera la tâche 1 de la liste des projets 12 tâches
4

Ceci est maintenant supporté (j'utilise la version 2.3.6 mais il pourrait être introduit plus tôt). Vous pouvez l'utiliser dans le sérialiseur direcly comme ceci:

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

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

    class Meta: 
     model = Album 

Hope it helps :)

+1

Cet extrait de code est-il correct? D'où provient ImageFeatureSerializer? Et le modèle de SongSerializer est un autre SongSerializer? – user798719

+0

Désolé, je convertissais une partie de mon propre code pour l'adapter à l'exemple ci-dessus, et j'étais un peu pressé. Cela devrait fonctionner. Merci! –

+0

@RaresMusina À quoi ressemblerait une requête POST maintenant? –

Questions connexes