В Django Rest Framework как сделать так, чтобы представление на основе функции откатывало все сделанные изменения, если что-то не получилось

У меня есть api endpoint, в который пользователь отправляет ключевую пару file_field: File в типе содержимого multipart. Функция должна обновить каждый документ и создать историю об изменении. Затем она должна завершить сессию, которую пользователь использовал для этого изменения. Если документ не может быть обновлен или историческая не может быть создана все операции и изменения должны откатиться назад, как архивировать это. Вот мой текущий вид базы функций:

@transaction.atomic
@api_view(['POST'])
@parser_classes([JSONParser, MultiPartParser])
@permission_classes([HasSpecialSessionPermission])
def update_documents(request):
    user = request.user
    special_session = SpecialSessionConfiguration.objects.filter(user=user, completed=False).first()
    lot = DefaultLotModel.objects.filter(user=user, call__active=True).first()
    for key, uploaded_file in request.FILES.items():
        try:
            validate_file_size(uploaded_file)
            if key != 'financial_form' and key != 'power_point':
                validate_file_extension(uploaded_file)
        except ValidationError as e:
            return Response({'message': str(e)}, status=status.HTTP_400_BAD_REQUEST)

        if special_session.special_session_fields.filter(
                field_name=get_field_number(SPECIAL_SESSION_FIELD, key)).exists():
            if hasattr(lot, key):
                current_file = getattr(lot, key)
                if current_file:
                    setattr(lot, key, uploaded_file)
                    LotDocumentHistory.objects.create(
                        lot=lot,
                        old_file=current_file,
                        field_name=key,
                    )

                setattr(lot, key, uploaded_file)
                lot.save()
            else:
                for child_field in ['first_lots', 'second_lots', 'third_lots']:
                    child_lot = getattr(lot, child_field, None)
                    if child_lot and hasattr(child_lot, key):
                        current_file = getattr(child_lot, key)
                        if current_file:
                            LotDocumentHistory.objects.create(
                                lot=lot,
                                old_file=current_file,
                                field_name=key,
                            )

                        setattr(child_lot, key, uploaded_file)
                        child_lot.save()
        elif special_session.extra_files:
            try:
                data = {'name': key, 'file': uploaded_file, 'lot': lot.pk}
                serializer = ExtraFileSerializer(data=data)
                serializer.is_valid(raise_exception=True)
                serializer.save()
            except ValidationError as ve:
                error_dict = ve.get_full_details()
                response_data = {
                    ERROR_TYPE: VALIDATION_ERROR,
                    ERRORS: error_dict,
                    MESSAGE: get_validation_error_message(error_dict)
                }
                return Response(data=response_data, status=status.HTTP_400_BAD_REQUEST)
    special_session.completed = True
    special_session.save()

    return Response(data={'lot_id': lot.pk}, status=status.HTTP_200_OK)

Если одно из обновлений и сохранений завершилось неудачно, все операции должны вернуться назад

Вернуться на верх