Django REST 框架 - 序列化程序、read_only 和 DRF 嵌套路由器,如何设置父级?



我有以下简单的待办事项列表模型:

class TodoList(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255)

class Todo(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
todo_title = models.CharField(max_length=64)
todo_body = models.TextField()
completed = models.BooleanField(default=False)
list = models.ForeignKey(TodoList, on_delete=models.CASCADE, related_name='messages')

我正在尝试做的是使用 drf 嵌套路由器设置嵌套路由。 例如:

/api/v1/todo-lists/                           <- List Todo Lists
/api/v1/todo-lists/{LIST_ID}/                 <- CRUD a Todo list
/api/v1/todo-lists/{LIST_ID}/todos/           <- List todos for a particular list
/api/v1/todo-lists/{LIST_ID}/todos/{TODO_ID}/ <- CRUD for a particular todo

我有一个待办事项序列化程序:

class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'todo_title', 'todo_body', 'completed', 'list',)
read_only_fields = ('id', 'list',)

和一个 TodoByList 视图集:

class TodoByListViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
serializer_class = TodoSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
return Todo.objects.filter(list_id=self.kwargs['todolist_pk'])
def create(self, request, todolist_pk=None):
todo_list = get_object_or_404(TodoList, pk=todolist_pk)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

列表视图效果很好,但是对于创建,我有点像第 22 条军规。 我的 Todo 模型的列表参数是必需的(理所当然),因此perform_create不起作用,因为未设置list。 但是,如果我从序列化程序的read_only_fields中删除list.is_valid失败,因为我没有将列表 ID 与我的请求数据一起传递。 我需要做的是注入从 url 参数检索到的todo_list实例,但我不确定如何做到这一点。

您需要从序列化程序的read_only_fields中删除列表。然后,您需要将todo_list id 传递给序列化程序。例如:

def create(self, request, todolist_pk=None):
todo_list = get_object_or_404(TodoList, pk=todolist_pk)
dict_data = dict(request.data)
dict_data['list'] = todo_list.id
serializer = self.get_serializer(data=dict_data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

最新更新