bgneal@695: """Views for the user_photos application."""
bgneal@722: import json
bgneal@722: 
bgneal@695: from django.conf import settings
bgneal@704: from django.contrib.auth import get_user_model
bgneal@695: from django.contrib.auth.decorators import login_required
bgneal@722: from django.http import (HttpResponse, HttpResponseForbidden,
bgneal@722:     HttpResponseNotAllowed)
bgneal@704: from django.shortcuts import render, redirect, get_object_or_404
bgneal@704: from django.views.generic import ListView
bgneal@710: from django.views.decorators.http import require_POST
bgneal@704: from django.utils.decorators import method_decorator
bgneal@710: from django.contrib import messages
bgneal@695: 
bgneal@695: from user_photos.forms import UploadForm
bgneal@704: from user_photos.models import Photo
bgneal@718: from user_photos.s3 import delete_photos
bgneal@695: 
bgneal@695: 
bgneal@695: @login_required
bgneal@695: def upload(request):
bgneal@695:     """This view function receives an uploaded image file from a user.
bgneal@695:     The photo will be resized if necessary and a thumbnail image will be
bgneal@695:     created. The image and thumbnail will then be uploaded to the Amazon
bgneal@695:     S3 service for storage.
bgneal@695: 
bgneal@695:     """
bgneal@695:     form = None
bgneal@696:     uploads_enabled = settings.USER_PHOTOS_ENABLED
bgneal@695: 
bgneal@695:     if uploads_enabled:
bgneal@695:         if request.method == 'POST':
bgneal@696:             form = UploadForm(request.POST, request.FILES, user=request.user)
bgneal@695:             if form.is_valid():
bgneal@696:                 photo = form.save()
bgneal@696:                 return redirect(photo)
bgneal@695:         else:
bgneal@696:             form = UploadForm(user=request.user)
bgneal@695: 
bgneal@695:     return render(request, 'user_photos/upload_form.html', {
bgneal@695:         'enabled': uploads_enabled,
bgneal@695:         'form': form,
bgneal@695:         },
bgneal@695:         status=200 if uploads_enabled else 503)
bgneal@704: 
bgneal@704: 
bgneal@722: def upload_ajax(request):
bgneal@722:     """This view is the ajax version of the upload function, above.
bgneal@722: 
bgneal@722:     We return a JSON object response to the client with the following name
bgneal@722:     & value pairs:
bgneal@722:             'success' : false for failure and true for success
bgneal@722:             'msg' : string error message if success is false
bgneal@722:             'url' : the image URL as a string if success
bgneal@722: 
bgneal@722:     If a non-200 status code is returned the response will simply be a text
bgneal@722:     string error message.
bgneal@722: 
bgneal@722:     """
bgneal@722:     if not request.user.is_authenticated():
bgneal@724:         return HttpResponseForbidden('Please login to use this service')
bgneal@722:     if not request.is_ajax() or request.method != 'POST':
bgneal@724:         return HttpResponseNotAllowed('This method is not allowed')
bgneal@722: 
bgneal@722:     ret = {'success': False, 'msg': '', 'url': ''}
bgneal@722:     if settings.USER_PHOTOS_ENABLED:
bgneal@722:         form = UploadForm(request.POST, request.FILES, user=request.user)
bgneal@722:         if form.is_valid():
bgneal@722:             photo = form.save()
bgneal@722:             ret['success'] = True
bgneal@722:             ret['url'] = photo.url
bgneal@722:         else:
bgneal@722:             # gather form error messages
bgneal@722:             errors = []
bgneal@722:             non_field_errors = form.non_field_errors().as_text()
bgneal@722:             if non_field_errors:
bgneal@722:                 errors.append(non_field_errors)
bgneal@722:             for field_errors in form.errors.values():
bgneal@722:                 errors.append(field_errors.as_text())
bgneal@722:             ret['msg'] = '\n'.join(errors)
bgneal@722:     else:
bgneal@722:         ret['msg'] = 'Photo uploads are temporarily disabled'
bgneal@722: 
bgneal@722:     return HttpResponse(json.dumps(ret), content_type='application/json')
bgneal@722: 
bgneal@722: 
bgneal@704: class GalleryView(ListView):
bgneal@704:     """A ListView for displaying a user's photos"""
bgneal@704: 
bgneal@704:     template_name = 'user_photos/gallery.html'
bgneal@704:     context_object_name = 'photos'
bgneal@704:     paginate_by = 50
bgneal@704:     allow_empty = True
bgneal@704: 
bgneal@704:     def get_queryset(self):
bgneal@704:         self.gallery_owner = get_object_or_404(get_user_model(),
bgneal@704:                                     username=self.kwargs['username'])
bgneal@704:         return Photo.objects.filter(user=self.gallery_owner).order_by('-upload_date')
bgneal@704: 
bgneal@704:     def get_context_data(self, **kwargs):
bgneal@704:         context = super(GalleryView, self).get_context_data(**kwargs)
bgneal@704:         context['gallery_owner'] = self.gallery_owner
bgneal@704:         return context
bgneal@704: 
bgneal@704:     @method_decorator(login_required)
bgneal@704:     def dispatch(self, *args, **kwargs):
bgneal@704:         return super(GalleryView, self).dispatch(*args, **kwargs)
bgneal@710: 
bgneal@710: 
bgneal@710: @login_required
bgneal@710: @require_POST
bgneal@710: def delete(request):
bgneal@718:     """A view function to allow a user to delete their own photos."""
bgneal@718: 
bgneal@718:     ret_view, username = 'user_photos-gallery', request.user.username
bgneal@718: 
bgneal@718:     if not settings.USER_PHOTOS_ENABLED:
bgneal@718:         messages.error(request, "This function is disabled temporarily")
bgneal@718:         return redirect(ret_view, username)
bgneal@718: 
bgneal@710:     photo_ids = []
bgneal@710:     for photo_id in request.POST.getlist('photo_id'):
bgneal@710:         try:
bgneal@710:             n = int(photo_id)
bgneal@710:         except ValueError:
bgneal@710:             continue
bgneal@710:         photo_ids.append(n)
bgneal@710: 
bgneal@710:     count = 0
bgneal@710:     if photo_ids:
bgneal@710:         qs = Photo.objects.filter(user=request.user, pk__in=photo_ids)
bgneal@718:         count = len(qs)
bgneal@718:         if count:
bgneal@718:             delete_photos(qs)
bgneal@718:             qs.delete()
bgneal@710: 
bgneal@718:     msg = "{} photo{} deleted".format(count, '' if count == 1 else 's')
bgneal@718:     messages.add_message(request,
bgneal@718:             messages.SUCCESS if count > 0 else messages.WARNING,
bgneal@718:             msg)
bgneal@710: 
bgneal@718:     return redirect(ret_view, username)