I have a api endpoint that the user will send a key pair of file_field: File in the multipart content type. The function need to update every document and create a history about the change. Then It should complete the session that the user used to do this change. If a document couldn't be updated or a historic couldn't be created all the operations and changes should roll back how to archive this. This is my current function base view:
@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)
If one of the update and saves fails all operations should go back