Skip to content

Instantly share code, notes, and snippets.

@mentix02
Last active August 27, 2020 05:53
Show Gist options
  • Save mentix02/c8e09b100839ba714a101aa9c3bfe213 to your computer and use it in GitHub Desktop.
Save mentix02/c8e09b100839ba714a101aa9c3bfe213 to your computer and use it in GitHub Desktop.
class UpdatePostAPIView(APIView):
permission_classes = (IsAuthenticated,)
parser_classes = (MultiPartParser, FormParser)
@staticmethod
def get(request: WSGIRequest, pk: int) -> Response:
try:
# Solves the problem of checking whether user owns post referenced.
post = Post.objects.filter(user=request.user).get(pk=pk)
except Post.DoesNotExist:
return Response({'detail': 'Not found.'}, status=status.HTTP_404_NOT_FOUND)
else:
return Response(PostSerializer(post).data)
@staticmethod
def put(request: WSGIRequest, pk: int) -> Response:
try:
# Solves the problem of checking whether user owns post referenced.
post = Post.objects.filter(user=request.user).get(pk=pk)
except Post.DoesNotExist:
return Response({'detail': 'Not found.'}, status=status.HTTP_404_NOT_FOUND)
# Provides a list of ids for images to be deleted.
to_delete = set(map(int, request.POST.getlist('to_delete')))
# Provides a list of additional (or replacement) images to be uploaded.
additional_images = request.FILES.getlist('images')
post_images = post.images.all()
post_images_count = post_images.count()
final_images_count = post_images_count - len(to_delete) + len(additional_images)
if final_images_count > 5 or final_images_count <= 0:
# Check if the difference between the number of images requested to be deleted
# and the total number of images currently in post added with the total number
# new images to be uploaded lies between 0 and 5.
return Response(
{'detail': 'Cannot have post with 0 images.'},
status=status.HTTP_400_BAD_REQUEST,
)
elif to_delete.issubset(set(post_images.values_list('pk', flat=True))):
# Default case if everything goes right since only two situations can evaluate
# the above clause to be true -
# 1. Either no new images were provided and thus an empty set will always be
# a subset to all the images already existing in the post OR
# 2. The ids that were provided in to_delete were valid ids that belong to the
# id list of the images reversely to the post.
# Bulk delete images if any.
post_images.filter(id__in=to_delete).delete()
# Upload images if any.
for image in additional_images:
image_serializer = ImageSerializer(
data={'file': image, 'post': post.id}
)
if image_serializer.is_valid():
image_serializer.save()
else:
return Response(
{'error': 'Invalid image data.'},
status=status.HTTP_409_CONFLICT,
)
else:
# Everything has gone right so far and a sanitary update of caption is left.
if request.POST.get('caption', False):
post.caption = request.POST['caption']
post.save()
return Response({'success': 'Updated.'}, status=status.HTTP_200_OK)
else:
return Response({'error': 'Not found.'}, status=status.HTTP_404_NOT_FOUND)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment