2016-05-05 7 views
0

ファイルの拡張子によっては、ファイルを特定のAWSバケットに保存する必要があります。私はstorageオプションに関数を渡そうとしましたが、upload_toがどのように動的に定義されているかに似ています。モデルのストレージオプションを動的に選択する方法.FileField?

しかし、これは望ましい結果を与えません。私のテンプレートで、hrefをdocument.docfile.urlにしようとすると、リンクは機能しません。

# -*- 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を関数として渡さなっている:シェルのチェックイン

、これは

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ファイルであるだろう起こります文字列ではなく、その方法はupload_file_toは?どうすれば修正できますか?

答えて

0

カスタムストレージバックエンドを作成し、S3BotoStorageのさまざまなビットを上書きする方がよい場合があります。 特に、bucket_nameをプロパティにすると、必要な振る舞いを得ることができます。

EDIT:

その上のビットを展開するには、S3BotoStorage.__init__ためsourceは、オプションの引数としてbucketを持っています。さらに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) 
+0

どのように動作するのかわかりません。実行時にファイル名の拡張子でバケットを決定する必要があります。 S3BotoStorageから継承する新しいクラスを作成した場合でも、固定バケットを選択する必要はありませんか、同じ問題が発生しますか? – thatharmansingh

+0

私は[this](http://pastebin.com/raw/GQJ6ad72)でしたが、同じ問題が存在します。つまり、docfile.bucketに文字列値の代わりに関数が割り当てられ、docfile.urlにアクセスするとエラーが発生します。 msgstr "strと関数を連結できません" msgid。 – thatharmansingh

+0

ソースコードを見ると、初期化するときに選択する必要はありません。バケットプロパティをオーバーライドすると、すべてのインスタンス変数にアクセスできます。その時点でファイル名にアクセスできるようになりますので、使用するバケットを適切に計算できるようになります。どちらの方法でS3BotoStorageのソースコードを見てください。あまりにも多くのメソッドをオーバーライドする必要はありません。 – Paul

関連する問題