DRF Serializer пользовательское создание - PullRequest
0 голосов
/ 02 февраля 2020

Не знаю, правильно ли я это делаю, но у меня возникают проблемы с сохранением некоторых отношений с сериализаторами DRF.

Допустим, у меня есть MessageBoard и несколько MessageBoardPosts

В сообщении есть сериализатор, например:

class MessageBoardPostSerializer(serializers.ModelSerializer):
  class Meta:
      model = MessageBoardPost
      fields = '__all__'

Я хочу добавить сообщение, опубликовав его в / api / messageBoards / [PK] / create_post / Для этого я добавил действие в ViewBoard Viewset :

@action(detail=True, methods=['post'], permission_classes=[MatchesMessageboardVisibility])
def create_post(self, request, pk=None):
    # Messageboard to post to
    messageBoard = MessageBoard.objects.get(pk=pk)

    if messageBoard is not None:
        serializer = MessageBoardPostSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
    return Response(serializer.data)

Поскольку MessageBoard является обязательным FK для сообщения, я получаю ошибки проверки при создании сообщения в наборе.

Какой лучший способ решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 02 февраля 2020

Сериализатор (я предполагаю, что "message_board" - это ForeignKey в модели MessageBoardPost):

class MessageBoardPostSerializer(serializers.ModelSerializer):
  # this is read only by default which means serializer will not require that field 
  message_board = serializers.StringRelatedField() 

  class Meta:
      model = MessageBoardPost
      fields = '__all__'

Действие набора:

@action(detail=True, methods=['post'], permission_classes=[MatchesMessageboardVisibility])
def create_post(self, request, pk=None):
    # Messageboard to post to
    messageBoard = get_object_or_404(MessageBoard, pk=pk)

    serializer = MessageBoardPostSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)

    # here you can pass data without validation directly to the save method
    serializer.save(message_board=messageBoard)
    return Response(serializer.data)
  • вы должны записать свои переменные в стиле snake_case как "доска объявлений" и т. д. c.
  • для более продвинутых пользователей, вы должны сделать URL-адрес как / api / message -boards / PK / posts /, где вы будете POST свои сообщения, а доска сообщений должна быть предварительно выбрана в переопределенном начальном методе
1 голос
/ 02 февраля 2020

Вы можете передать MessageBoard в качестве контекста сериализатору:

views.py

from django.shortcuts import get_object_or_404

@action(detail=True, methods=['post'], permission_classes=[MatchesMessageboardVisibility])
def create_post(self, request, pk=None):
    # Messageboard to post to
    message_board = get_object_or_404(MessageBoard, pk=pk)

    context = {'message_board': message_board}
    serializer = MessageBoardPostSerializer(data=request.data, context=context)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data)

serializers.py

class MessageBoardPostSerializer(serializers.ModelSerializer):
    class Meta:
        model = MessageBoardPost
        fields = '__all__'

    def create(self, validated_data):
        post = MessageBoardPost(**validated_data)
        post.message_board = self.context['message_board']
        post.save()
        return post

...