Я пытаюсь создать вложенные объекты в Django Rest Framework в соответствии с документами .
Вот мои модели.py:
import uuid
from django.db import models
from django.utils.http import int_to_base36
from django.core.validators import MaxValueValidator, MinValueValidator
from django.contrib.auth import get_user_model
ID_LENGTH = 12
USER = get_user_model()
def slug_gen():
"""Generates a probably unique string that can be used as a slug when routing
Starts with a uuid, encodes it to base 36 and shortens it
"""
#from base64 import b32encode
#from hashlib import sha1
#from random import random
slug = int_to_base36(uuid.uuid4().int)[:ID_LENGTH]
return slug
class List(models.Model):
"""Models for lists
"""
slug = models.CharField(max_length=ID_LENGTH, default=slug_gen, editable=False)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
created_by = models.ForeignKey(USER, on_delete=models.CASCADE, related_name='list_created_by')
created_at = models.DateTimeField(auto_now_add=True)
modified_by = models.ForeignKey(USER, on_delete=models.SET_NULL, null=True,
related_name='list_modified_by')
modified_at = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=255)
description = models.CharField(max_length=255, blank=True, default='')
is_public = models.BooleanField(default=False)
def __str__(self):
return self.title
class Item(models.Model):
"""Models for list items
"""
slug = models.CharField(max_length=ID_LENGTH, default=slug_gen, editable=False)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
modified_at = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=255)
description = models.CharField(max_length=255, blank=True, default='')
list = models.ForeignKey(List, on_delete=models.CASCADE, related_name='items')
order = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(10)])
class Meta:
unique_together = ('list', 'order')
ordering = ['order']
def __unicode__(self):
return '%d: %s' % (self.order, self.title)
Вот мой serializers.py:
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('id', 'title', 'description', 'slug', 'modified_at', 'list', 'order')
class ListSerializer(serializers.ModelSerializer):
items = ItemSerializer(many=True)
print('hello one')
# automatically set created_by as the current user
created_by = serializers.PrimaryKeyRelatedField(
read_only=True,
default=serializers.CurrentUserDefault()
)
class Meta:
model = List
fields = ('id', 'title', 'description', 'is_public',
'slug', 'created_by', 'created_at',
'modified_by', 'modified_at', 'items')
def create(self, validated_data):
print('hello two')
items_data = validated_data.pop('items', None)
print(validated_data)
print(items_data)
newlist = List.objects.create(**validated_data)
for item_data in items_data:
Item.objects.create(list=newlist, **item_data)
return list
А вот список отправляемых данных с данными:
curl 'http://localhost:3000/api/v1/content/lists/' -H 'Authorization: Token ae367b73efbb7d6849af421d553e9c243b4baf7b' -H 'Origin: http://localhost:3000' -H 'Accept-Encoding: gzip, deflate, br' -H 'dataType: json' -H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' -H 'Content-Type: application/json' -H 'Accept: */*' -H 'Referer: http://localhost:3000/newlist' -H 'Connection: keep-alive' --data-binary '{"title":"Hats","description":"","items":[{"title":"Fedora","order":1}]}' --compressed
Насколько я вижу, это соответствует примеру в документации, и я думаю, что данные правильно отформатированы с помощью 'items' в виде массива объектов. Однако, когда я пытаюсь создать новый список с элементом, происходит сбой с этой ошибкой:
{"items":[{"list":["This field is required."]}]}
Я прочитал это сообщение : я вижу ту же ошибку, если использую API с возможностью просмотра, поэтому, похоже, другая проблема.
Почему возникает ошибка? 'список' предоставляется в коде согласно примеру. Это UUID, это требует специальной обработки?
Вторая проблема, которая затрудняет мне отладку ... почему операторы print в методе 'create' ничего не записывают в консоль? «hello one» появляется при запуске сервера, но «hello two» в консоли никогда не появляется.
Большое спасибо за любую помощь!
Обновление: с этого поста кажется, что создание вложенных объектов работает наоборот, как я и ожидал - ItemSerializer запускается до ListSerializer, даже если элемент не может существовать без списка. Удаление «списка» из полей ItemSerializer означает, что создание теперь успешно, ура! И мой текст отладки напечатан, показывая, что теперь вызывается метод создания ListSerializer.
Вот определение рабочих полей в ItemSerializer:
fields = ('id', 'title', 'description', 'slug', 'modified_at', 'order')
У меня также была опечатка в ListSerializer. return list
должно быть return newlist
.