Django Serializer: Как я могу проверить экземпляр модели? - PullRequest
0 голосов
/ 13 сентября 2018

Я довольно новичок в сериализаторах Django и все еще не понимаю, как они работают.

У меня довольно общий сценарий, в котором я вызываю свой API, который просто устанавливает поле в моём объекте модели и сохраняет его (предположим, что запись уже существует, и она только обновляется). Однако мне нужно проверить этот объект модели перед его сохранением.

api.py

@detail_route(methods=['POST'], url_path='submit-draft')
def submit_draft(self, request, *args, **kwargs):
    booking = self.get_object()

    # serializer with custom validations.
    serializer = self.get_serializer(booking)
    serializer.is_valid(raise_exception=True)

    booking.submit_draft(by=request.user)
    booking.save()

    data = serializers.BookingDetailSerializer(booking, context={'request': request}).data

    return response.Ok(data)

serializers.py

class BookingCreateUpdateSerializer(serializers.ModelSerializer):
    date = serializers.CharField()

    duration = serializers.IntegerField(required=True, )

    created_by = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault(), )

    modified_by = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault(), )
    ....

    class Meta:
    model = models.Booking
        fields = [
        'title',
        'date',
        'duration',
        'client',
        'created_by',
        'modified_by',
        ....
    ]

Однако я получаю эту ошибку:

AssertionError: Cannot call '.is_valid()' as no 'data=' keyword argument was passed when instantiating the serializer instance.

Я понимаю, что сериализатор ожидает словарь, а не реальный модальный объект. Но я не могу понять, как достичь того, чего я хочу, т.е. проверить модель объекта. Кто-нибудь может предложить, пожалуйста, правильный подход?

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Это то, что, наконец, сработало, потратив почти целый день на царапины на голове.

api.py

@detail_route(methods=['POST'], url_path='submit-draft')
def submit_draft(self, request, *args, **kwargs):
    # Step1. Get current model instance.
    booking = self.get_object()

    # Step2. Serialize the model instance using same serializer as in Step5.
    booking_data = serializers.BookingDetailSerializer(booking, context={'request': 
    request}).data

    # Step3. Deserialize the data from Step2 (using `BookingCreateUpdateSerializer` serializer 
    as mentioned in description and check for validations.
    serializer = self.get_serializer(data=booking_data)
    serializer.is_valid(raise_exception=True)       

    # Step4. If no validation error, set the required field and save the instance.
    booking.submit_draft(by=request.user)
    booking.save()

    # Step5. Return response.
    data = serializers.BookingDetailSerializer(booking, context={'request': request}).data

    return response.Ok(data)

Я узнал кое-что больше о сериализаторах сегодня. Мы можем передавать экземпляры модели в разные сериализаторы и изменять ее форму в соответствии с нашими требованиями.

0 голосов
/ 13 сентября 2018

Вы можете использовать сериализатор для:

1) сериализации вашего объекта в словарь.В этом случае вам не нужно вызывать is_valid, поскольку объект уже создан и имеет допустимые значения.Таким образом, вы можете сделать следующее:

serializer = BookingCreateUpdateSerializer(booking)

return Response(serializer.data)

2) сериализовать ввод и создать новый объект, используя сериализатор.В этом случае input является словарем, и его необходимо сначала проверить перед вызовом save.И вы можете сделать что-то вроде этого:

serializer = BookingCreateUpdateSerializer(data=input_dict)
serializer.is_valid()
serializer.save()

Обновить, чтобы ответить на комментарий

Вы можете сделать следующее, чтобы обновить экземпляр с помощью сериализатора:

serializer = BookingCreateUpdateSerializer(booking, data=input_data_to_update, partial=True)
serializer.is_valid()

instance = serializer.save()

# and serialize the updated instance for response using another serializer
output_data = BookingDetailSerializer(instance).data
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...