通过为Azure云存储编写的自定义存储设置Django Imagefield模型属性的URL [英] Setting url of Django Imagefield model attribute via custom storage written for Azure Cloud Storage
问题描述
我有一个Django网络应用程序,用户上传图片,其他人查看。我有一个自定义存储类在这个应用程序上传图像文件到Azure云存储。目前图像正在上传成功,但是它们的网址没有被设置。因此,我的模板中的以下代码产生了一个
单击我们可以在此容器中的blob列表中的容器名称。我们可以复制一个项目的URL,在浏览器中访问以进行检查。
根据我的理解,如果要在上传到Azure存储之后显示图像,我们只需要对原始代码进行一些修改。
在自定义存储类中,假设函数 url()
应该返回正确的URL。在我的测试中,我直接返回URL字符串进行快速测试:
def geturl(self,name):
返回'%s /%s /%s'%('http://garyteststorage.blob.core.windows.net','mycontainer',name)
我们可以将函数 _save()
的返回值修改为 URL
图像类,而不是
名称
:
url = self.geturl(name)
return url
#return name
在models.py 中:
def upload_path(instance,filename):
return'上传自定义存储 - {}'。format(filename)
类照片(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 中:
如果form.is_valid():
newImage =照片(image_file = request.FILES ['image_file'])
newImage.save()
imageurl = newImage.image_file
html =< img src =%s>< / img> <峰; br>中%imageurl
#在POST之后重定向到文档列表
返回HttpResponse(html)
I have a Django web app where users upload images and others view them. I have a custom storage class in this app to upload image files to Azure Cloud Storage. Currently images are being uploaded successfully, but their urls are not being set. Thus, the following code in my template yields a broken image:
{% if entry.image_file %}
<img src="{{ entry.image_file.url }}"></img><br>
{% endif %}
Can you point out what my custom storage class is missing? Here's how it appears in my models.py currently:
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 )
The example I'm following is here. I have looked at django documentation for custom file storage, and if you scroll through the code I've pasted above, I've defined a url(self, name):
method. Yet this doesn't get called (I've tested it with a print
statement). Please advise!
The Blobs in Azure Blob Storage have their own unique urls for accessing. The URL is in the format: http://<your_storage_name>.blob.core.windows.net/<container_name>/<blob_name>
, you can directly access it in browser, if you set the access permission of blob to public.
To your issue, if it is not sensitive to your images in Blob Storage, you can simply set access permission to public blob
to allow public read access to the blobs in the container, but not the container properties and metadata.
Login in Azure mange portal, click storage tab in left nav, click your storage name in the list to step in your storage manage page, click CONTAINERS tab, select the specific container name, click the EDIT button in bottom, change the access permission and click OK button to save the configuration:
Click the container name we can step in the list of blobs in this container. We can copy the URL of an item, visit in browser to have a check.
And per my understanding, if you want to show the images after uploading to Azure storage, we just need a few modification on the original code.
In the custom storage class, assume the function url()
should return the correct the URL. In my test, I directly return the URL string for a quick test:
def geturl(self,name):
return '%s/%s/%s' % ('http://garyteststorage.blob.core.windows.net','mycontainer', name)
And we can modify the return of function _save()
to the URL
of the image class instead of name
:
url = self.geturl(name)
return url
#return name
In 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 )
As before, it will save the image name in database, and after modification, it will save the full url of blob in database.
code snippet In 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)
这篇关于通过为Azure云存储编写的自定义存储设置Django Imagefield模型属性的URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!