Use Django views for handling blobstore uploads

前端 未结 4 791
星月不相逢
星月不相逢 2021-02-11 04:16

In stead of using the BlobstoreUploadHandler supplied in AppEngine, I\'d prefer to use a Django view, so I can keep all the urls and view functions together. Howeve

4条回答
  •  臣服心动
    2021-02-11 04:54

    I had the same problem yesterday. Thanks to your post I realizad that the problem was django and his class views. I finally use a code that I have since 2011 and it still works. It does not use BlobstoreUploadHandler, but it gets the blob_infos from the request after automatically upload it to blobstore.

    You can use that function in the next way from your callback django function or class (I finally did not try it in a class view from Django but I think it will work. Currently I'm using it in a function view from Django with its request):

    media_blobs = get_uploads(request, populate_post=True)
    

    The function is the next:

    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
    

    The last function is not mine. I do not remember where I got it three or four years ago. But I think it will help someone.

    UPDATE:

    You also can use a view handler of webapp.WSGIApplication and at the same time use django. This way will allow you to use BlobstoreUploadHandler and BlobstoreDownloadHandler (for video stream as example). You only need to add the view class in main.py and create its handler:

    class ServeVideoHandler(blobstore_handlers.BlobstoreDownloadHandler):
        def get(self, resource):
            ...
    
    downloader_handler = webapp.WSGIApplication([('/pathA/pathB/([A-Za-z0-9\-\=_]+)', ServeVideoHandler),], debug=True)
    

    And in app.yaml add the handler before the script main.application that contains your django app.

    - url: /pathA/pathB/(.+)
      script: main.downloader_handler
    

提交回复
热议问题