# HG changeset patch # User Brian Neal # Date 1379558045 18000 # Node ID bf5340705d0ce378d627c7c9247de7e6c984b9ba # Parent 846cf9a06a046818c4fb2f6ec5276a22a68a8e4d Completed view to delete user photos. Still need to modify the admin to delete not just the model instance but the S3 bucket keys. diff -r 846cf9a06a04 -r bf5340705d0c core/s3.py --- a/core/s3.py Wed Sep 18 18:33:52 2013 -0500 +++ b/core/s3.py Wed Sep 18 21:34:05 2013 -0500 @@ -10,8 +10,6 @@ class S3Bucket(object): """This class abstracts an Amazon S3 bucket. - We currently only support upload functionality. - """ def __init__(self, access_key, secret_key, base_url, bucket_name): self.conn = S3Connection(access_key, secret_key) @@ -71,6 +69,28 @@ key.make_public() return '{}{}/{}'.format(self.base_url, self.name, key_name) + def delete_keys(self, key_urls): + """Deletes a set of keys, specified as a list of URLs. The URLs could + have been returned by one or more of the upload_* methods. + + Returns the number of keys that were successfully deleted. + + """ + if len(key_urls) == 0: + return 0 + + prefix = '{}{}/'.format(self.base_url, self.name) + prefix_len = len(prefix) + + keys = [] + for url in key_urls: + if url.startswith(prefix): + key = url[prefix_len:] + keys.append(key) + + response = self.bucket.delete_keys(keys, quiet=True) + return len(key_urls) - len(response.errors) + def _make_key(self, key_name, metadata): """Private method to create a key and optionally apply metadata to it. diff -r 846cf9a06a04 -r bf5340705d0c sg101/templates/user_photos/gallery.html --- a/sg101/templates/user_photos/gallery.html Wed Sep 18 18:33:52 2013 -0500 +++ b/sg101/templates/user_photos/gallery.html Wed Sep 18 21:34:05 2013 -0500 @@ -4,6 +4,34 @@ {% block custom_css %} {% endblock %} +{% block custom_js %} +{% if user == gallery_owner %} + +{% endif %} +{% endblock %} {% block content %}

Photo Gallery for {{ gallery_owner.username }}

@@ -27,7 +55,8 @@ {% if photos %} {% if user == gallery_owner %} -
{% csrf_token %} + {% csrf_token %} {% for photo in photos %}
diff -r 846cf9a06a04 -r bf5340705d0c sg101/templates/user_photos/photo_detail.html --- a/sg101/templates/user_photos/photo_detail.html Wed Sep 18 18:33:52 2013 -0500 +++ b/sg101/templates/user_photos/photo_detail.html Wed Sep 18 21:34:05 2013 -0500 @@ -61,7 +61,14 @@ Upload another photo
  • Gallery See all my photos
  • - + + +{% csrf_token %} + + + + {% else %}

    Gallery diff -r 846cf9a06a04 -r bf5340705d0c user_photos/s3.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/user_photos/s3.py Wed Sep 18 21:34:05 2013 -0500 @@ -0,0 +1,40 @@ +"""Module for all S3 related operations for the user_photos application.""" + +import logging + +from django.conf import settings + +from core.s3 import S3Bucket + + +logger = logging.getLogger(__name__) + + +def delete_photos(qs): + """Delete the photos stored on S3 for the given Photo queryset. + + Returns the number of photos actually deleted. + + """ + + bucket = S3Bucket(settings.USER_PHOTOS_ACCESS_KEY, + settings.USER_PHOTOS_SECRET_KEY, + settings.USER_PHOTOS_BASE_URL, + settings.USER_PHOTOS_BUCKET) + + key_urls = [] + for photo in qs: + key_urls.append(photo.url) + key_urls.append(photo.thumb_url) + req_cnt = len(key_urls) + + logger.info("Requesting deletion of %d user photo(s) from S3", req_cnt) + + act_cnt = bucket.delete_keys(key_urls) + + if act_cnt == req_cnt: + logger.info("Deleted %d user photo(s) from S3", act_cnt) + else: + logger.warning("Deleted %d user photo(s) out of %d", act_cnt, req_cnt) + + return act_cnt diff -r 846cf9a06a04 -r bf5340705d0c user_photos/views.py --- a/user_photos/views.py Wed Sep 18 18:33:52 2013 -0500 +++ b/user_photos/views.py Wed Sep 18 21:34:05 2013 -0500 @@ -10,6 +10,7 @@ from user_photos.forms import UploadForm from user_photos.models import Photo +from user_photos.s3 import delete_photos @login_required @@ -69,6 +70,14 @@ @login_required @require_POST def delete(request): + """A view function to allow a user to delete their own photos.""" + + ret_view, username = 'user_photos-gallery', request.user.username + + if not settings.USER_PHOTOS_ENABLED: + messages.error(request, "This function is disabled temporarily") + return redirect(ret_view, username) + photo_ids = [] for photo_id in request.POST.getlist('photo_id'): try: @@ -80,11 +89,14 @@ count = 0 if photo_ids: qs = Photo.objects.filter(user=request.user, pk__in=photo_ids) - count = qs.count() - qs.delete() + count = len(qs) + if count: + delete_photos(qs) + qs.delete() - if count: - msg = "{} photo{} deleted".format(count, '' if count == 1 else 's') - messages.add_message(request, messages.INFO, msg) + msg = "{} photo{} deleted".format(count, '' if count == 1 else 's') + messages.add_message(request, + messages.SUCCESS if count > 0 else messages.WARNING, + msg) - return redirect('user_photos-gallery', username=request.user.username) + return redirect(ret_view, username)