django-storages获得完整的S3网址

时间:2016-06-23 13:10:58

标签: python django amazon-s3

我有几个使用django-storage与Amazon S3的课程

class Cache(models.Model):
    identifier = models.TextField(blank=True, null=True)
    cache_file = models.FileField(upload_to="cache")

现在我需要获取缓存文件位置的URL。

cache = cache.objects.get(identifier=identifier)
cache_file = cache.cache_file

缓存文件是FieldFile对象,其中包含storage个对象。

在数据库中我只看到我之前保存的值cache/file.json

在这种情况下,我不需要获取文件,而是文件所在的完整URL 我怎么能得到这个?

3 个答案:

答案 0 :(得分:3)

我知道这个问题已经得到解答,但万一有人在偶然发现这个问题时正在寻找我需要的东西......

我发现大型查询从模型实例(report.file.url)中拉出url会导致在我需要提取大量记录的情况下出现糟糕的性能,因为Django会在每个记录执行数据库查询时以这种方式访问​​模型字段。下面是一个替代方法的示例实现,您可以预先执行整个查询,如果需要,仍然可以获取URL。

from django.core.files.storage import get_storage_class
from . import models

# instance of the current storage class
media_storage = get_storage_class()()

# grabs all of my reports at once and stores them in a list of dicts
# instead of separate Report instances
report_list = models.Report.objects.values()

# stick the urls into the my records
report_list = [
        {**report, "url": media_storage.url(report["file"])} 
        for report in report_list
]

答案 1 :(得分:2)

该文件应位于:

cache = cache.objects.get(identifier=identifier)
cache_file = cache.cache_file
cache_file_url = cache.cache_file.url

调用此方法获取完整的S3 URL,但您应该设置django存储来获取此URL。

答案 2 :(得分:0)

尽管我们现在有2个不错的答案,但值得探讨一下media_storage.url()通话背后的内容:

***假设我们在django-storages中安装了settings.py,并具有正确的设置,例如:

# Defualt File Storage (Remote/Cloud Storage Service)
# https://docs.djangoproject.com/en/3.0/ref/settings/#default-file-storage
DJANGO_REMOTE_STORAGE_ON = bool(os.environ.get('DJANGO_REMOTE_STORAGE_ON'))

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' if DJANGO_REMOTE_STORAGE_ON else 'django.core.files.storage.FileSystemStorage'

if DEFAULT_FILE_STORAGE == 'storages.backends.s3boto3.S3Boto3Storage':
    AWS_STORAGE_BUCKET_NAME = os.environ.get('DJANGO_AWS_STORAGE_BUCKET_NAME')
    AWS_ACCESS_KEY_ID = os.environ.get('DJANGO_AWS_ACCESS_KEY_ID')
    AWS_SECRET_ACCESS_KEY = os.environ.get('DJANGO_AWS_SECRET_ACCESS_KEY')
    AWS_S3_REGION_NAME = os.environ.get('DJANGO_AWS_S3_REGION_NAME')
    AWS_S3_ENDPOINT_URL = os.environ.get('DJANGO_AWS_S3_ENDPOINT_URL')
    AWS_S3_OBJECT_PARAMETERS = { 'CacheControl': 'max-age=86400', }
    AWS_DEFAULT_ACL = 'public-read'
    AWS_BUCKET_ACL = 'public-read'
    AWS_IS_GZIPPED = True
    AWS_S3_USE_SSL = True
    AWS_QUERYSTRING_AUTH = False
from django.core.files.storage import get_storage_class

media_storage = get_storage_class()()

// Assume we know some sort of ID:
id = 1

// Retrieve the object instance from the ID (or other attribute field)
obj = Object.objects.get(id=id)

// Assuming we have some file field called "file":
boto_s3_url = media_storage.url(name=obj.file.name)

这可确保无论使用哪种存储方法,我们都将始终检索绝对URI位置,例如"https://<AWS_S3_REGION_NAME>.<AWS_S3_ENDPOINT_URL>/<AWS_STORAGE_BUCKET_NAME>/<UPLOADS_TO>/<FILENAME>"

例如https://nyc3.digitaloceanspaces.com/asencis/datasets/records/files/CHANDRA.2.0.source.tsv