How to use Azure's BlobService object to upload a file associated to a Django model

狂风中的少年 提交于 2020-01-06 12:16:07

问题


I have a Django app where users upload photos and descriptions. Here's a typical model which facilitates that user behavior:

class Photo(models.Model):
    description = models.TextField(validators=[MaxLengthValidator(500)])
    submitted_on = models.DateTimeField(auto_now_add=True)
    image_file = models.ImageField(upload_to=upload_to_location, null=True, blank=True )

Notice the image_file attribute has upload_to argument, which is fed the upload directory and file name of the image_file. The upload_to_location method takes care of that; assume it works correctly.

Now I want to upload each image to Azure Cloud Storage. The python snippet to do that is explained here. Using that, I tried to write my own custom storage that saves images to Azure. It's buggy though, and I need help in cleaning it up. Here's what I've done:

Changed the image_file attribute in models.py to:

image_file = models.ImageField("Tasveer dalo:",upload_to=upload_to_location, storage=OverwriteStorage(), null=True, blank=True )

And then created a separate storage.py in my app folder that has:

from django.conf import settings
from django.core.files.storage import Storage
from azure.storage.blob import BlobService

class OverwriteStorage(Storage):
    def __init__(self,option=None):
        if not option:
            pass
    def _save(name,content):
        blob_service = BlobService(account_name='accname', account_key='key')
        PROJECT_ROOT = path.dirname(path.abspath(path.dirname(__file__)))
        try:
            blob_service.put_block_blob_from_path(
                    'containername',
                    name,
                    path.join(path.join(PROJECT_ROOT,'uploads'),name),
                    x_ms_blob_content_type='image/jpg'
            )
            return name
        except:
            print(sys.exc_info()[1])
            return 0
    def get_available_name(self,name):
        return name

This set up doesn't work, and returns the error: _save() takes exactly 2 arguments (3 given). Exception Location: /home/hassan/.virtualenvs/redditpk/local/lib/python2.7/site-packages/django/core/files/storage.py in save, line 48

How do I make this work? Has anyone used Azure-Storage python SDK with their Django projects in this way? Please advise.

Note: Originally, I was using the django-storages library, which obfuscated storage details from me, reducing everything to just some configuration to be entered in settings.py. But now, I need to remove django-storages from the equation, and solely use the Azure-Storage python SDK for the purpose.

Note: Ask for more information in case you need it


回答1:


According your error message, you missed parameter in function _save() which should be complete in the format like _save(self,name,content).

And additionally, it seems that you want put the images directly to Azure Storage which are uploaded from client forms. If so, I found a repo in github which builds a custom azure storage class for Django models. We can get leverage it to modify your application. For more details, refer to https://github.com/Rediker-Software/django-azure-storage/blob/master/azure_storage/storage.py

And here are my code snippets, models.py:

from django.db import models
from django.conf import settings
from django.core.files.storage import Storage
from azure.storage.blob import BlobService
accountName = 'accountName'
accountKey = 'accountKey'

class OverwriteStorage(Storage):
    def __init__(self,option=None):
        if not option:
            pass
    def _save(self,name,content):
        blob_service = BlobService(account_name=accountName, account_key=accountKey)
        import mimetypes

        content.open()

        content_type = None

        if hasattr(content.file, 'content_type'):
            content_type = content.file.content_type
        else:
            content_type = mimetypes.guess_type(name)[0]

        content_str = content.read()


        blob_service.put_blob(
            'mycontainer',
            name,
            content_str,
            x_ms_blob_type='BlockBlob',
            x_ms_blob_content_type=content_type
        )

        content.close()

        return name
    def get_available_name(self,name):
        return name

def upload_path(instance, filename):
    return 'uploads-from-custom-storage-{}'.format(filename)

class Photo(models.Model):
   image_file = models.ImageField(upload_to=upload_path, storage=OverwriteStorage(), null=True, blank=True )


来源:https://stackoverflow.com/questions/34293603/how-to-use-azures-blobservice-object-to-upload-a-file-associated-to-a-django-mo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!