2013-02-20 1 views
9

Использование Django restDjango REST: Вложенный объект добавить на создание (POST) не просто обновить (PUT)

Ниже, как у меня была serializer.py.

class ProfileSerializer(serializers.ModelSerializer): 


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

Тип является flatview

Затем я изменил его так «тип» был вложен для каждого профиля, как это ...

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

теперь это работает отлично, но я не могу теперь только обновляйте «тип», когда в деталях профиля он теперь доступен только для чтения.

Как добавить тип при создании нового профиля и сохранить его вложенное представление?

Надеюсь, я объяснил это четко.

UPDATE:

Хорошо, я только что прочитал это:

Примечание: Вложенные сериализаторов пригодны только только для чтения представлений, так как есть случаи, когда они имеют неоднозначный или неочевидное поведение, если используется при обновлении экземпляров. Для представлений «чтение-запись» вы всегда должны использовать плоское представление, используя один из подклассов RelatedField.

Так что это имеет смысл. Так что я изменил его ....

type = serializers.PrimaryKeyRelatedField() 

Это ставит его обратно в POST и работе, но это позор, я не могу представить «тип» с ID и имя, так что имеет смысл в конечный пользователь?

ответ

12

Полная поддержка перезаписываемых вложенными сериализаторов является work in progress, но в то же время одно решение переопределить метод create в представлении в каждом случае:

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) 

Вероятно, не идеально, но это работает для меня пока не появится правильный путь.

+0

я обнаружил, что SlugRelatedField позволяют мне в настоящее время перехода от ид к чему-то осмысленному как название или имя поля, но тем используя плоское поле, не вложенное. Я буду повторять попытку с вложенным и посмотреть, может ли переопределить работу. – jason

+0

Можете ли вы объяснить, как мы можем проверить другие поля здесь? – CrazyGeek

6

У меня была такая же проблема в Джанго-покоя рамки, и я создал View для этого очень быстро, вы можете найти его в этом суть: https://gist.github.com/edulix/5311365

Основы использования CRUDManyToManyView является следующее :

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

сериализаторы.ру

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

Затем вы можете сделать что-то вроде:

  • GET проектов/12/задач/ перечислим задачи проекта
  • POST-проекты/12/tasks/1/ который добавит задачу 1 в списке проекта 12 задач (задача 1 должна уже существовать)
  • УДАЛЕНИЯ проекты/12/задачи/1/ который удалит задание 1 из списка проектов 12 задач
4

Это поддерживается (я использую версию 2.3.6, но может быть введена ранее). Вы можете использовать его в сериализаторе direcly так:

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

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

    class Meta: 
     model = Album 

Надеется, что это помогает :)

+1

Правильно ли этот фрагмент кода? Откуда появился ImageFeatureSerializer? И модель SongSerializer - это еще один SongSerializer? – user798719

+0

Извините, я конвертировал часть своего собственного кода, чтобы он соответствовал приведенному выше примеру, и был в спешке. Это должно сработать. Благодаря! –

+0

@RaresMusina Как выглядит запрос POST? –

Смежные вопросы