annotate user_photos/views.py @ 1200:b9514abc2a67

Initial commit of ssg101.
author Brian Neal <bgneal@gmail.com>
date Sat, 24 Jun 2023 16:06:51 -0500
parents 364f8ec48612
children
rev   line source
bgneal@695 1 """Views for the user_photos application."""
bgneal@722 2 import json
bgneal@722 3
bgneal@695 4 from django.conf import settings
bgneal@704 5 from django.contrib.auth import get_user_model
bgneal@695 6 from django.contrib.auth.decorators import login_required
bgneal@722 7 from django.http import (HttpResponse, HttpResponseForbidden,
bgneal@971 8 HttpResponseNotAllowed, JsonResponse)
bgneal@704 9 from django.shortcuts import render, redirect, get_object_or_404
bgneal@1158 10 from django.views.generic import DetailView
bgneal@704 11 from django.views.generic import ListView
bgneal@710 12 from django.views.decorators.http import require_POST
bgneal@704 13 from django.utils.decorators import method_decorator
bgneal@710 14 from django.contrib import messages
bgneal@695 15
bgneal@971 16 from user_photos.forms import HotLinkImageForm, UploadForm
bgneal@704 17 from user_photos.models import Photo
bgneal@718 18 from user_photos.s3 import delete_photos
bgneal@695 19
bgneal@695 20
bgneal@695 21 @login_required
bgneal@695 22 def upload(request):
bgneal@695 23 """This view function receives an uploaded image file from a user.
bgneal@695 24 The photo will be resized if necessary and a thumbnail image will be
bgneal@695 25 created. The image and thumbnail will then be uploaded to the Amazon
bgneal@695 26 S3 service for storage.
bgneal@695 27
bgneal@695 28 """
bgneal@695 29 form = None
bgneal@696 30 uploads_enabled = settings.USER_PHOTOS_ENABLED
bgneal@695 31
bgneal@695 32 if uploads_enabled:
bgneal@695 33 if request.method == 'POST':
bgneal@696 34 form = UploadForm(request.POST, request.FILES, user=request.user)
bgneal@695 35 if form.is_valid():
bgneal@696 36 photo = form.save()
bgneal@696 37 return redirect(photo)
bgneal@695 38 else:
bgneal@696 39 form = UploadForm(user=request.user)
bgneal@695 40
bgneal@695 41 return render(request, 'user_photos/upload_form.html', {
bgneal@695 42 'enabled': uploads_enabled,
bgneal@695 43 'form': form,
bgneal@1158 44 'V3_DESIGN': True,
bgneal@695 45 },
bgneal@695 46 status=200 if uploads_enabled else 503)
bgneal@704 47
bgneal@704 48
bgneal@722 49 def upload_ajax(request):
bgneal@722 50 """This view is the ajax version of the upload function, above.
bgneal@722 51
bgneal@722 52 We return a JSON object response to the client with the following name
bgneal@722 53 & value pairs:
bgneal@722 54 'success' : false for failure and true for success
bgneal@722 55 'msg' : string error message if success is false
bgneal@722 56 'url' : the image URL as a string if success
bgneal@722 57
bgneal@722 58 If a non-200 status code is returned the response will simply be a text
bgneal@722 59 string error message.
bgneal@722 60
bgneal@722 61 """
bgneal@722 62 if not request.user.is_authenticated():
bgneal@724 63 return HttpResponseForbidden('Please login to use this service')
bgneal@722 64 if not request.is_ajax() or request.method != 'POST':
bgneal@724 65 return HttpResponseNotAllowed('This method is not allowed')
bgneal@722 66
bgneal@722 67 ret = {'success': False, 'msg': '', 'url': ''}
bgneal@722 68 if settings.USER_PHOTOS_ENABLED:
bgneal@722 69 form = UploadForm(request.POST, request.FILES, user=request.user)
bgneal@722 70 if form.is_valid():
bgneal@722 71 photo = form.save()
bgneal@722 72 ret['success'] = True
bgneal@722 73 ret['url'] = photo.url
bgneal@722 74 else:
bgneal@722 75 # gather form error messages
bgneal@722 76 errors = []
bgneal@722 77 non_field_errors = form.non_field_errors().as_text()
bgneal@722 78 if non_field_errors:
bgneal@722 79 errors.append(non_field_errors)
bgneal@722 80 for field_errors in form.errors.values():
bgneal@722 81 errors.append(field_errors.as_text())
bgneal@722 82 ret['msg'] = '\n'.join(errors)
bgneal@722 83 else:
bgneal@722 84 ret['msg'] = 'Photo uploads are temporarily disabled'
bgneal@722 85
bgneal@722 86 return HttpResponse(json.dumps(ret), content_type='application/json')
bgneal@722 87
bgneal@722 88
bgneal@1096 89 def upload_ajax_v3(request):
bgneal@1096 90 """This view is the V3 ajax version of the upload function, above.
bgneal@1096 91
bgneal@1096 92 We return a JSON object response to the client with the following name
bgneal@1096 93 & value pairs:
bgneal@1096 94 'msg' : string error message if success is false
bgneal@1096 95 'url' : the image URL as a string if success
bgneal@1096 96 """
bgneal@1096 97 ret = {'error_msg': '', 'url': ''}
bgneal@1096 98 status_code = 400
bgneal@1096 99
bgneal@1096 100 if not request.user.is_authenticated():
bgneal@1096 101 ret['error_msg'] = 'Please login to use this service'
bgneal@1096 102 return JsonResponse(ret, status=403)
bgneal@1096 103 if not request.is_ajax() or request.method != 'POST':
bgneal@1096 104 ret['error_msg'] = 'This method is not allowed'
bgneal@1096 105 return JsonResponse(ret, status=405)
bgneal@1096 106
bgneal@1096 107 if settings.USER_PHOTOS_ENABLED:
bgneal@1096 108 form = UploadForm(request.POST, request.FILES, user=request.user)
bgneal@1096 109 if form.is_valid():
bgneal@1096 110 try:
bgneal@1096 111 photo = form.save()
bgneal@1096 112 ret['url'] = photo.url
bgneal@1096 113 status_code = 200
bgneal@1096 114 except Exception as ex:
bgneal@1096 115 ret['error_msg'] = str(ex)
bgneal@1096 116 status_code = 500
bgneal@1096 117 else:
bgneal@1096 118 # gather form error messages
bgneal@1096 119 errors = []
bgneal@1096 120 non_field_errors = form.non_field_errors().as_text()
bgneal@1096 121 if non_field_errors:
bgneal@1096 122 errors.append(non_field_errors)
bgneal@1096 123 for field_errors in form.errors.values():
bgneal@1096 124 errors.append(field_errors.as_text())
bgneal@1096 125 ret['msg'] = '\n'.join(errors)
bgneal@1096 126 else:
bgneal@1096 127 ret['msg'] = 'Photo uploads are temporarily disabled'
bgneal@1096 128 status_code = 403
bgneal@1096 129
bgneal@1096 130 return JsonResponse(ret, status=status_code)
bgneal@1096 131
bgneal@1096 132
bgneal@704 133 class GalleryView(ListView):
bgneal@704 134 """A ListView for displaying a user's photos"""
bgneal@704 135
bgneal@704 136 template_name = 'user_photos/gallery.html'
bgneal@704 137 context_object_name = 'photos'
bgneal@704 138 paginate_by = 50
bgneal@704 139 allow_empty = True
bgneal@704 140
bgneal@704 141 def get_queryset(self):
bgneal@704 142 self.gallery_owner = get_object_or_404(get_user_model(),
bgneal@704 143 username=self.kwargs['username'])
bgneal@704 144 return Photo.objects.filter(user=self.gallery_owner).order_by('-upload_date')
bgneal@704 145
bgneal@704 146 def get_context_data(self, **kwargs):
bgneal@704 147 context = super(GalleryView, self).get_context_data(**kwargs)
bgneal@704 148 context['gallery_owner'] = self.gallery_owner
bgneal@1158 149 context['V3_DESIGN'] = True
bgneal@1158 150 context['page'] = context['page_obj']
bgneal@704 151 return context
bgneal@704 152
bgneal@704 153 @method_decorator(login_required)
bgneal@704 154 def dispatch(self, *args, **kwargs):
bgneal@704 155 return super(GalleryView, self).dispatch(*args, **kwargs)
bgneal@710 156
bgneal@710 157
bgneal@1158 158 class PhotoView(DetailView):
bgneal@1158 159 """A DetailView for displaying a user's photo"""
bgneal@1158 160
bgneal@1158 161 model = Photo
bgneal@1158 162
bgneal@1158 163 def get_context_data(self, **kwargs):
bgneal@1158 164 context = super(PhotoView, self).get_context_data(**kwargs)
bgneal@1158 165 context['V3_DESIGN'] = True
bgneal@1158 166 return context
bgneal@1158 167
bgneal@1158 168
bgneal@710 169 @login_required
bgneal@710 170 @require_POST
bgneal@710 171 def delete(request):
bgneal@718 172 """A view function to allow a user to delete their own photos."""
bgneal@718 173
bgneal@718 174 ret_view, username = 'user_photos-gallery', request.user.username
bgneal@718 175
bgneal@718 176 if not settings.USER_PHOTOS_ENABLED:
bgneal@718 177 messages.error(request, "This function is disabled temporarily")
bgneal@718 178 return redirect(ret_view, username)
bgneal@718 179
bgneal@710 180 photo_ids = []
bgneal@710 181 for photo_id in request.POST.getlist('photo_id'):
bgneal@710 182 try:
bgneal@710 183 n = int(photo_id)
bgneal@710 184 except ValueError:
bgneal@710 185 continue
bgneal@710 186 photo_ids.append(n)
bgneal@710 187
bgneal@710 188 count = 0
bgneal@710 189 if photo_ids:
bgneal@710 190 qs = Photo.objects.filter(user=request.user, pk__in=photo_ids)
bgneal@718 191 count = len(qs)
bgneal@718 192 if count:
bgneal@718 193 delete_photos(qs)
bgneal@718 194 qs.delete()
bgneal@710 195
bgneal@718 196 msg = "{} photo{} deleted".format(count, '' if count == 1 else 's')
bgneal@718 197 messages.add_message(request,
bgneal@718 198 messages.SUCCESS if count > 0 else messages.WARNING,
bgneal@718 199 msg)
bgneal@710 200
bgneal@718 201 return redirect(ret_view, username)
bgneal@971 202
bgneal@971 203
bgneal@971 204 def hotlink_image(request):
bgneal@971 205 """This view is responsible for accepting an image URL from a user and
bgneal@971 206 converting it to a URL pointing into our S3 bucket if necessary.
bgneal@971 207
bgneal@971 208 We return a JSON object response to the client with the following name
bgneal@971 209 & value pairs:
bgneal@971 210 'error_msg': string error message if an error occurred
bgneal@971 211 'url': the image URL as a string if success
bgneal@971 212 """
bgneal@971 213 ret = {'error_msg': '', 'url': ''}
bgneal@971 214 status_code = 400
bgneal@971 215
bgneal@971 216 if not request.user.is_authenticated():
bgneal@971 217 ret['error_msg'] = 'Please login to use this service'
bgneal@972 218 return JsonResponse(ret, status=403)
bgneal@971 219 if not request.is_ajax() or request.method != 'POST':
bgneal@971 220 ret['error_msg'] = 'This method is not allowed'
bgneal@972 221 return JsonResponse(ret, status=405)
bgneal@971 222
bgneal@971 223 if settings.USER_PHOTOS_ENABLED:
bgneal@972 224 form = HotLinkImageForm(request.POST, user=request.user)
bgneal@971 225 if form.is_valid():
bgneal@971 226 try:
bgneal@971 227 ret['url'] = form.save()
bgneal@971 228 status_code = 200
bgneal@971 229 except Exception as ex:
bgneal@971 230 ret['error_msg'] = str(ex)
bgneal@971 231 status_code = 500
bgneal@971 232 else:
bgneal@971 233 # gather form error messages
bgneal@971 234 errors = []
bgneal@971 235 non_field_errors = form.non_field_errors().as_text()
bgneal@971 236 if non_field_errors:
bgneal@971 237 errors.append(non_field_errors)
bgneal@971 238 for field_errors in form.errors.values():
bgneal@971 239 errors.append(field_errors.as_text())
bgneal@971 240 ret['error_msg'] = '\n'.join(errors)
bgneal@971 241 else:
bgneal@971 242 ret['error_msg'] = 'Image linking is temporarily disabled'
bgneal@971 243 status_code = 403
bgneal@971 244
bgneal@971 245 return JsonResponse(ret, status=status_code)