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