使用Django视图处理blobstore上载
与使用AppEngine中提供的使用Django视图处理blobstore上载,django,google-app-engine,Django,Google App Engine,与使用AppEngine中提供的BlobstoreUploadHandler不同,我更喜欢使用Django视图,这样我可以将所有URL和视图函数保持在一起。但是,我找不到如何获取上传文件的blob键!(与上载处理程序类似)。我看到了BlobstoreUploadHandler使用了,但我认为Django没有提供这种功能 看起来AppEngine实际上用这个描述符替换了文件内容,但是AppEngine把密钥放在哪里呢 我开始怀疑blob密钥在不使用webapp框架时丢失,因为UploadedFil
BlobstoreUploadHandler
不同,我更喜欢使用Django视图,这样我可以将所有URL和视图函数保持在一起。但是,我找不到如何获取上传文件的blob键
!(与上载处理程序类似)。我看到了BlobstoreUploadHandler
使用了,但我认为Django没有提供这种功能
看起来AppEngine实际上用这个描述符替换了文件内容,但是AppEngine把密钥放在哪里呢
我开始怀疑blob密钥在不使用webapp框架时丢失,因为UploadedFile对象没有key()方法。如您所述,是开源的,因此您可以看到他们用于从请求参数中解析密钥的逻辑。请注意,只包含来自查询字符串和请求正文(用于POST请求)的变量。因此,您可能希望从djnago请求的对象开始。我花了很长时间才找到,但是
内容类型:message/external body
需要额外的参数,才能找到实际的文件,在AppEngine的情况下,这是blob键。但是,Django不支持这些额外的content_类型参数,因此它们确实会在过程中丢失。似乎有一个补丁,但我不认为它在AppEngine Django版本中
我昨天也有同样的问题。多亏了你的帖子,我才意识到问题出在django和他的班级观点上。我终于使用了一个自2011年以来一直使用的代码,它仍然有效。它不使用BlobstoreUploadHandler,但在将请求自动上载到blobstore后,它会从请求中获取blob_信息
您可以在回调django函数或类中以下一种方式使用该函数(我最终没有在django的类视图中尝试它,但我认为它会起作用。目前,我正在django的函数视图中使用它及其请求):
下一个功能是:
import cgi
from google.appengine.ext import blobstore
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)
ja = request.META['wsgi.input']
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:
if isinstance(field, list):
request.POST[key] = [val.value for val in field]
else:
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
最后一个功能不是我的。我不记得三四年前在哪里买的。但我认为它会帮助一些人
更新:
您还可以使用webapp.WSGIApplication的视图处理程序,同时使用django。这种方式将允许您使用BlobstoreUploadHandler和BlobstoreDownloadHandler(以视频流为例)。只需在main.py中添加视图类并创建其处理程序:
class ServeVideoHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, resource):
...
downloader_handler = webapp.WSGIApplication([('/pathA/pathB/([A-Za-z0-9\-\=_]+)', ServeVideoHandler),], debug=True)
在app.yaml中,在包含django应用程序的脚本main.application之前添加处理程序
- url: /pathA/pathB/(.+)
script: main.downloader_handler
密钥信息不直接在文件中,而是在file.blobstore\u info.key()中
将包含图像的表单发布到使用blobstore创建的url。创建\u上传\u url()
:
创建的url将把图像保存在blobstore中,并将请求(使用修改过的文件对象)重定向到/add\u image/
为/add_image/
定义url模式和视图并处理图像:
def add_action_image(request):
image = request.data.get('image')
image_key = image.blobstore_info.key()
... addl' logic to save a record with the image_key...
问题是,在这个请求对象(在SDK中)中,我找不到任何与blob键相关的内容(请参阅有问题的编辑)。我想知道当Django的WSGIRequest被使用时它是否会丢失。这本可以解决我的问题是的,但我想我当时使用了另一种解决方法(因为我无法修补AppEngine Django)Ops,我没有注意到这一年,但我想它会帮助有同样问题的人。当然,Noio已经解决了这个问题。
media_blobs = get_uploads(request, populate_post=True)
import cgi
from google.appengine.ext import blobstore
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)
ja = request.META['wsgi.input']
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:
if isinstance(field, list):
request.POST[key] = [val.value for val in field]
else:
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
class ServeVideoHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, resource):
...
downloader_handler = webapp.WSGIApplication([('/pathA/pathB/([A-Za-z0-9\-\=_]+)', ServeVideoHandler),], debug=True)
- url: /pathA/pathB/(.+)
script: main.downloader_handler
from google.appengine.ext import blobstore
upload_url = blobstore.create_upload_url('/add_image/')
def add_action_image(request):
image = request.data.get('image')
image_key = image.blobstore_info.key()
... addl' logic to save a record with the image_key...