使用Django视图处理blobstore上载

使用Django视图处理blobstore上载,django,google-app-engine,Django,Google App Engine,与使用AppEngine中提供的BlobstoreUploadHandler不同,我更喜欢使用Django视图,这样我可以将所有URL和视图函数保持在一起。但是,我找不到如何获取上传文件的blob键!(与上载处理程序类似)。我看到了BlobstoreUploadHandler使用了,但我认为Django没有提供这种功能 看起来AppEngine实际上用这个描述符替换了文件内容,但是AppEngine把密钥放在哪里呢 我开始怀疑blob密钥在不使用webapp框架时丢失,因为UploadedFil

与使用AppEngine中提供的
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...