Как динамически выбрать вариант хранения для моделей.FileField?
В зависимости от расширения файла, я хочу, чтобы файл был сохранен в определенном сегменте AWS. Я попытался передать функцию storage
вариант, аналогичный тому, как upload_to
динамически определяется.
Однако это не дает желаемых результатов. В моем шаблоне, когда я пытаюсь перейти к document.docfile.url, ссылка не работает.
Проверка в оболочке, это происходит
Document.objects.all()[0].docfile.storage.bucket
<Bucket: <function aws_bucket at 0x110672050>>
Document.objects.all()[0].docfile.storage.bucket_name
<function myproject.myapp.models.aws_bucket>
Желаемое поведение будет
Document.objects.all()[0].docfile.storage.bucket_name
'asynch-uploader-txt'
Document.objects.all()[0].docfile.storage.bucket
<Bucket: asynch-uploader-txt>
Это мое models.py
файл:
# -*- coding: utf-8 -*-
from django.db import models
from storages.backends.s3boto import S3BotoStorage
def upload_file_to(instance, filename):
import os
from django.utils.timezone import now
filename_base, filename_ext = os.path.splitext(filename)
return 'files/%s_%s%s' % (
filename_base,
now().strftime("%Y%m%d%H%M%S"),
filename_ext.lower(),
)
def aws_bucket(instance, filename):
import os
filename_base, filename_ext = os.path.splitext(filename)
return 'asynch-uploader-%s' %(filename_ext[1:])
class Document(models.Model):
docfile = models.FileField(upload_to=upload_file_to,storage=S3BotoStorage(bucket=aws_bucket))
Почему aws_bucket
получать как функцию, а не строку, способ, которым upload_file_to
является? Как я могу это исправить?
1 ответ
Для того, что вы пытаетесь сделать, вам может быть лучше создать собственный бэкэнд хранилища и просто переопределить различные биты S3BotoStorage. В частности, если вы делаете bucket_name
свойство, вы должны иметь возможность получить поведение, которое вы хотите.
РЕДАКТИРОВАТЬ:
Чтобы немного расширить это, источник для S3BotoStorage.__init__
имеет bucket
в качестве необязательного аргумента. Кроме того, ведро, когда оно используется в классе, является @param
, что позволяет легко переопределить. Следующий код не протестирован, но его должно быть достаточно, чтобы дать вам отправную точку
class MyS3BotoStorage(S3BotoStorage):
@property
def bucket(self):
if self._filename.endswith('.jpg'):
return self._get_or_create_bucket('SomeBucketName')
else:
return self._get_or_create_bucket('SomeSaneDefaultBucket')
def _save(self, name, content):
# This part might need some work to normalize the name and all...
self._filename = name
return super(MyS3BotoStorage, self)._save(name, content)