public
Last active

  • Download Gist
blogstore_helper.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
"""
A helper for the app engine blobstore API and Django.
 
Works with the appengine patch:
http://code.google.com/p/app-engine-patch/
 
Taken and inspired by:
http://appengine-cookbook.appspot.com/recipe/blobstore-get_uploads-helper-function-for-django-request/
 
Usage:
 
def upload_file(request):
try:
for upload in blogstore_helper.get_uploads(request,'file'):
file = BlobFile(blob=upload)
file.save()
return HttpResponseRedirect("/redirect/to/file/viewer/")
except:
# throw an error
return HttpResponseRedirect("/redirect/to/error/handler")
 
def serve_file(request, blob_id):
blob_id = str(urllib.unquote(blob_id))
blob = blobstore.BlobInfo.get(blob_id)
return blogstore_helper.send_blob(request, blob, save_as=True)
 
 
awesome,
harper@nata2.org
"""
 
import cgi
from google.appengine.ext import blobstore
from django.http import HttpResponse
import logging
 
def get_uploads(request, field_name=None, populate_post=False):
"""Get uploads sent to this handler.
 
Args:
field_name: Only select uploads that were sent as a specific field.
populate_post: Add the non blob fields to request.POST
 
Returns:
A list of BlobInfo records corresponding to each upload.
Empty list if there are no blob-info records for field_name.
"""
if hasattr(request,'__uploads') == False:
request.META['wsgi.input'].seek(0)
fields = cgi.FieldStorage(request.META['wsgi.input'], environ=request.META)
request.__uploads = {}
if populate_post:
request.POST = {}
for key in fields.keys():
field = fields[key]
if isinstance(field, cgi.FieldStorage) and 'blob-key' in field.type_options:
request.__uploads.setdefault(key, []).append(blobstore.parse_blob_info(field))
elif populate_post:
request.POST[key] = field.value
 
if field_name:
try:
return list(request.__uploads[field_name])
except KeyError:
return []
else:
results = []
for uploads in request.__uploads.itervalues():
results += uploads
return results
 
 
def send_blob(request, blob_key_or_info, content_type=None, save_as=None):
"""Send a blob-response based on a blob_key.
 
Sets the correct response header for serving a blob. If BlobInfo
is provided and no content_type specified, will set request content type
to BlobInfo's content type.
 
Args:
blob_key_or_info: BlobKey or BlobInfo record to serve.
content_type: Content-type to override when known.
save_as: If True, and BlobInfo record is provided, use BlobInfos
filename to save-as. If string is provided, use string as filename.
If None or False, do not send as attachment.
 
Raises:
ValueError on invalid save_as parameter.
"""
 
CONTENT_DISPOSITION_FORMAT = 'attachment; filename="%s"'
if isinstance(blob_key_or_info, blobstore.BlobInfo):
blob_key = blob_key_or_info.key()
blob_info = blob_key_or_info
else:
blob_key = blob_key_or_info
blob_info = None
 
logging.debug(blob_info)
response = HttpResponse()
response[blobstore.BLOB_KEY_HEADER] = str(blob_key)
 
if content_type:
if isinstance(content_type, unicode):
content_type = content_type.encode('utf-8')
response['Content-Type'] = content_type
else:
del response['Content-Type']
 
def send_attachment(filename):
if isinstance(filename, unicode):
filename = filename.encode('utf-8')
response['Content-Disposition'] = (CONTENT_DISPOSITION_FORMAT % filename)
 
if save_as:
if isinstance(save_as, basestring):
send_attachment(save_as)
elif blob_info and save_as is True:
send_attachment(blob_info.filename)
else:
if not blob_info:
raise ValueError('Expected BlobInfo value for blob_key_or_info.')
else:
raise ValueError('Unexpected value for save_as')
 
return response

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.