2017-01-27 2 views
0

Я пишу пример программы, где теги могут быть добавлены в todolist. Поэтому я создал образцы тегов. Но когда у меня возникли проблемы с добавлением этого в сериализатор Todo.Как отправить данные POST в вложенный Serializer Django Rest Framework?

Вот сериализаторы, которые я написал.

class TagSerializer(serializers.Serializer): 
    id = serializers.IntegerField(read_only=True) 
    name = serializers.CharField(required=False, max_length=100) 

    def create(self, validated_data): 
     return Tag.objects.create(**validated_data) 

class LocationSerializer(serializers.Serializer): 
    id = serializers.IntegerField(read_only=True) 
    latitude = serializers.CharField(max_length=100) 
    longitude = serializers.CharField(max_length=100) 

    def create(self, validated_data): 
     return Location.objects.create(**validated_data) 

class ToDoSerializer(serializers.Serializer): 
    id = serializers.IntegerField(read_only=True) 
    work_id = serializers.CharField(max_length=100) 
    tags = TagSerializer(many=True) 
    location = LocationSerializer() 

Я попытался отправить данные в сериализатор ToDo в качестве POST. Но как я могу отправить данные о местоположении и тегах в представление API.

APIView

class ToDoList(APIView): 
    def post(self, request, format=None): 
     serializer = ToDoSerializer(data=request.data) 
     if serializer.is_valid(): 
      serializer.save() 
      return Response(serializer.data, status=status.HTTP_201_CREATED) 
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 

Как я могу передать данные, как POST в ToDoList. Должен ли я писать пользовательские сообщения на ToDoSerializer?

Модель

class Tag(models.Model): 
    name = models.CharField(max_length=100) 

class Location(models.Model): 
    latitude = models.CharField(max_length=100) 
    longitude = models.CharField(max_length=100) 

class ToDo(models.Model): 
    work_id = models.CharField(max_length=100) 
    tags = models.ManyToManyField(Tag) 
    location = models.ForeignKey(Location) 

ответ

0

Вашего запрос данные POST должна выглядеть вложенную структуру, как заявлена ​​в вашем сериализаторе. И для этого вам следует использовать модельный сериализатор, потому что в противном случае вам нужно будет предоставить настраиваемый метод create на ToDoSerializer, поскольку обычный сериализатор не знает, как работать с вложенными структурами/моделями.

Итак, что я предлагаю это:

from rest_framework import serializers 

class ToDoSerializer(serializers.ModelSerializer): 
    tags = TagSerializer(many=True) 
    location = LocationSerializer() 

    class Meta: 
     model = ToDo 
     fields = ('tags', 'location', 'work_id', 'id') 

Ваше сообщение JSON должен выглядеть следующим образом:

{ 
    "work_id": 1, 
    "tags" : [ 
     {"name": "blah"}, 
     {"name": "blahblah"} 
    ], 

    "location": { 
     "latitude": 11.22, 
     "longitude": 33.44 
    } 

} 
+0

Как получить теги, которые уже созданы? –

+0

serializer.create get вызывается и возвращает экземпляр модели. Таким образом, вы получаете следующие задачи: 'instance.tags_set.all()' - имя по умолчанию для такой пары моделей. Но вы должны переписать это, предоставив 'related_name' для ManyToManyField. –

0

Вы должны обращаться в создании метод serialzier ToDoSerializer. документы writable-nested-representations

Вы можете попробовать что-то вроде этого:

def create(self, validated_data): 
    location_data = validated_data.pop('location') 
    tag_data = validated_data.pop('tags') 
    location = Location.objects.create(**location_data) 

    instance = ToDo.objects.create(location=location, **validated_data) 

    for dct in tag_data: 
     dct.pop('id', None) 
     tag, created = Tag.objects.get_or_create(**dct) 
     // tag = Tag.objects.create(**dct) 
     instance.tags.add(tag) 
    return instance 
+0

Как получить теги, которые уже созданы? –

+0

тег, созданный = Tag.objects.get_or_create (** dct) – Ashish

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