通过为 Azure 云存储编写的自定义存储设置 Django Imagefield 模型属性的 url

Setting url of Django Imagefield model attribute via custom storage written for Azure Cloud Storage

我有一个 Django 网络应用程序,用户可以在其中上传图片,其他人可以查看它们。我在此应用程序中有一个自定义存储 class,用于将图像文件上传到 Azure 云存储。当前图像正在成功上传,但是它们的 url 没有被设置。 因此,我的模板中的以下代码产生 broken image:

{% if entry.image_file %}
<img src="{{ entry.image_file.url }}"></img><br>
{% endif %}

你能指出我的自定义存储 class 缺少什么吗?这是它目前在我的 models.py 中的显示方式:

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

class OverwriteStorage(Storage):
    container = 'containername'
    account_name = accountName
    account_key = accountKey

    def __init__(self, account_name=None, account_key=None, container=None):

        if account_name is not None:
            self.account_name = account_name

        if account_key is not None:
            self.account_key = account_key

        if container is not None:
            self.container = container
    def __getstate__(self):
        return dict(
            account_name=self.account_name,
            account_key=self.account_key,
            container=self.container
        )
    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]
        print content_type
        content_str = content.read()
        blob_service.put_blob(
            'containername',
            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 _get_service(self):
        if not hasattr(self, '_blob_service'):
            self._blob_service = BlobService(
                account_name=self.account_name,
                account_key=self.account_key,
                protocol='http'
            )
        return self._blob_service
    def _open(self, name, mode='rb'):
        from django.core.files.base import ContentFile
        contents = self._get_service().get_blob(self.container, name)
        return ContentFile(contents)
    def _get_properties(self, name):
        return self._get_service().get_blob_properties(
            self.container,
            name
        )
    def _get_container_url(self):
        if not hasattr(self, '_container_url'):
            base_url = '{protocol}://{host}/{container}'
            if self.cdn_host:
                base_url = self.cdn_host
            self._container_url = base_url.format({
                'protocol': 'http',
                'host': self._get_service()._get_host(),
                'container': self.container,
            })
        return self._container_url
    def url(self, name):
        url = '%s/%s' % (self._get_container_url(), name)
        return url

class Entry(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, storage=OverwriteStorage(), null=True, blank=True )

我下面的示例是用于自定义文件存储的 here. I have looked at django documentation,如果您滚动浏览我在上面粘贴的代码,我已经定义了一个 url(self, name): 方法。然而这并没有被调用(我已经用 print 语句测试了它)。请指教!

Azure Blob 存储中的 Blob 有自己独特的 url 供访问。 URL的格式为:http://<your_storage_name>.blob.core.windows.net/<container_name>/<blob_name>,如果将blob的访问权限设置为public.

,则可以直接在浏览器中访问。

对于您的问题,如果它对您在 Blob 存储中的图像不敏感,您可以简单地将访问权限设置为 public blob 以允许 public 对容器中的 blob 进行读取访问,但是不是容器属性和元数据。

登录 Azure mange portal,单击左侧导航栏中的存储选项卡,单击列表中的存储名称以进入存储管理页面,单击 CONTAINERS 选项卡,select具体的容器名称,点击底部的编辑按钮,更改访问权限,点击确定按钮保存配置:

单击容器名称,我们可以进入该容器中的 blob 列表。我们可以复制一个项目的URL,在浏览器中访问查看。

根据我的理解,如果你想在上传到 Azure 存储后显示图像,我们只需要对原始代码进行一些修改。

在自定义存储 class 中,假设函数 url() 应该 return 正确 URL。在我的测试中,我直接return URL 字符串进行快速测试:

def geturl(self,name):
    return '%s/%s/%s' % ('http://garyteststorage.blob.core.windows.net','mycontainer', name)

并且我们可以将函数_save()的return修改为图像class的URL而不是name:

url = self.geturl(name)
return url
#return name

在models.py中:

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

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_path, storage=OverwriteStorage(), null=True, blank=True )

和之前一样,会把图片名称保存到数据库中,修改后,会把blob的全url保存到数据库中。

代码片段在view.py中:

if form.is_valid():
    newImage = Photo(image_file = request.FILES['image_file'])
    newImage.save()
    imageurl = newImage.image_file
    html = "<img src=%s></img><br>" %imageurl
    # Redirect to the document list after POST
    return HttpResponse(html)