【问题标题】:Setting url of Django Imagefield model attribute via custom storage written for Azure Cloud Storage通过为 Azure 云存储编写的自定义存储设置 Django Imagefield 模型属性的 url
【发布时间】:2015-12-16 21:20:13
【问题描述】:

我有一个 Django Web 应用程序,用户可以在其中上传图像,其他人可以查看它们。我在这个应用程序中有一个自定义存储类,用于将图像文件上传到 Azure 云存储。目前图片已成功上传,但未设置其网址。因此,我的模板中的以下代码生成broken image

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

您能指出我的自定义存储类缺少什么吗?以下是它目前在我的 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。我查看了django documentation 用于自定义文件存储,如果您滚动浏览我在上面粘贴的代码,我已经定义了一个url(self, name): 方法。然而这并没有被调用(我已经用print 语句对其进行了测试)。请指教!

【问题讨论】:

    标签: python django azure azure-cloud-services django-storage


    【解决方案1】:

    Azure Blob 存储中的 Blob 有自己的唯一 URL 可供访问。 URL格式为:http://&lt;your_storage_name&gt;.blob.core.windows.net/&lt;container_name&gt;/&lt;blob_name&gt;,如果设置blob的访问权限为public,可以直接在浏览器中访问。

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

    登录Azure mange portal,点击左侧导航中的storage选项卡,点击列表中你的storage名称进入你的storage管理页面,点击CONTAINERS选项卡,选择具体的容器名称,点击底部EDIT按钮,修改访问权限,点击OK按钮保存配置:

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

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

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

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

    并且我们可以将函数_save()的返回修改为图片类的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保存在数据库中。

    code sn -p 在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)
    

    【讨论】:

      猜你喜欢
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多