Я создаю приложение todo, в котором могут быть размещены комментарии.Для этого я сделал записываемый двойной вложенный сериализатор.Это работает, но метод обновления, который я написал, сложен для понимания, и поэтому я пытаюсь сделать его более читабельным.Есть ли лучший (или стандартный способ) написать метод обновления для двойного вложенного сериализатора?
Я прочитал документы для вложенных сериализаторов в официальных документах.https://www.django -rest-framework.org / api-guide / serializers /
models.py
class CustomUser(AbstractUser):
def __str__(self):
return self.email
class Todo(models.Model):
publisher = models.ForeignKey(
CustomUser,
on_delete=models.CASCADE,
related_name="todos",
)
title = models.CharField(max_length=50)
pub_date = models.DateTimeField('date published')
description = models.CharField(max_length=800)
is_done = models.BooleanField(default=False)
def __str__(self):
return self.title
class Comment(models.Model):
subject = models.ForeignKey(
Todo,
on_delete=models.CASCADE,
related_name="comments",
)
publisher = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
title = models.CharField(max_length=50, default=None)
pub_date = models.DateTimeField('date published')
description = models.CharField(max_length=800)
def __str__(self):
return self.description
serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = (
'url',
'title',
'pub_date',
'description',
)
read_only_fields = (
'url',
'pub_date',
)
class TodoSerializer(serializers.ModelSerializer):
comments = CommentSerializer(required=False, many=True)
class Meta:
model = Todo
fields = (
'url',
'title',
'pub_date',
'description',
'is_done',
'comments'
)
read_only_fields = (
'url',
'pub_date',
)
class UserSerializer(serializers.ModelSerializer):
todos = TodoSerializer(required=False, many=True)
class Meta:
model = CustomUser
fields = (
'url',
'email',
'username',
'todos',
)
read_only_fields = (
'url',
'email',
)
def create(self, validated_data):
todos = validated_data.pop('todos', None)
user = CustomUser.objects.create(**validated_data)
if todos is not None:
for todo in todos:
comments = todo.pop('comments', None)
Todo.objects.create(user=user, **todo)
if comments is not None:
for comment in comments:
Comment.objects.create(todo=todo, **comment)
return user
def update(self, instance, validated_data):
todos_data = validated_data.pop('todos', None)
todos = (instance.todos).all()
todos = list(todos)
instance.username = validated_data.get('username', instance.username)
instance.save()
if todos_data is not None:
for todo_data in todos_data:
comments_data = todo_data.pop('comments')
todo = todos.pop(0)
comments = (todo.comments).all()
comments = list(comments)
todo.title = todo_data.get('title', todo.title)
todo.description = todo_data.get('description', todo.description)
todo.is_done = todo_data.get('is_done', todo.is_done)
todo.save()
if comments_data is not None:
for comment_data in comments_data:
comment = comments.pop(0)
comment.title = comment_data.get('title', comment.title)
comment.description = comment_data.get('description', comment.description)
comment.save()
return instance
ожидается JSON
{
"url": "http://127.0.0.1:8000/api/users/4/",
"email": "api01@example.com",
"username": "api01",
"todos": [
{
"url": "http://127.0.0.1:8000/api/todo/1/",
"title": "first todo1.1",
"pub_date": "2019-07-04T12:40:56.799308+09:00",
"description": "description for first todo1.1",
"is_done": true,
"comments": [
{
"url": "http://127.0.0.1:8000/api/comment/1/",
"title": "first comment-1.1",
"pub_date": "2019-07-03T12:32:26.604598+09:00",
"description": "aaaaaaaaa-1.1"
},
{
"url": "http://127.0.0.1:8000/api/comment/2/",
"title": "second comment-1.1",
"pub_date": "2019-07-03T12:56:22.906482+09:00",
"description": "bbbbbbbbbbb-1.1"
}
]
}
]
}