2012-02-26 13 views
1

私は味覚にapiを作っているモデルがあります。私は手動で維持するファイルへのパスを格納するフィールドを持っています(私はFileFieldを使用していません、ユーザーはファイルをアップロードしていないので)。ここでは、モデルの要点れる:FileField in Tastypie

class FooModel(models.Model): 
    path = models.CharField(max_length=255, null=True) 
    ... 
    def getAbsPath(self): 
     """ 
     returns the absolute path to a file stored at location self.path 
     """ 
     ... 

ここでは私のtastypieの設定です:ファイルフィールドのAPIの

class FooModelResource(ModelResource): 
    file = fields.FileField() 

    class Meta: 
     queryset = FooModel.objects.all() 

    def dehydrate_file(self, bundle): 
     from django.core.files import File 
     path = bundle.obj.getAbsPath()   
     return File(open(path, 'rb')) 

これは、ファイルへのフルパスを返します。私はtastypieが実際のファイルまたは少なくともURLをファイルに提供できるようにしたい。それ、どうやったら出来るの?すべてのコードスニペットが高く評価されています。

はありがとう

答えて

4

ファイルからAPIを介してどのように公開されるかをURLスキームで決定します。ファイルやdehydrate_fileは実際には必要ありません(Tastypieでモデル自体のファイルの表現を変更しない限り)。代わりに、ModelResourceに追加のアクションを追加するだけです。例:

class FooModelResource(ModelResource): 
    file = fields.FileField() 

    class Meta: 
     queryset = FooModel.objects.all() 

    def override_urls(self): 
     return [ 
      url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/download%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('download_detail'), name="api_download_detail"), 
      ] 

    def download_detail(self, request, **kwargs): 
     """ 
     Send a file through TastyPie without loading the whole file into 
     memory at once. The FileWrapper will turn the file object into an 
     iterator for chunks of 8KB. 

     No need to build a bundle here only to return a file, lets look into the DB directly 
     """ 
     filename = self._meta.queryset.get(pk=kwargs[pk]).file 
     wrapper = FileWrapper(file(filename)) 
     response = HttpResponse(wrapper, content_type='text/plain') #or whatever type you want there 
     response['Content-Length'] = os.path.getsize(filename) 
     return response 

GET .../API/foomodel/3/

戻り値: { ... 'ファイル': 'localPathに/ファイル名。拡張子'、 ... }

GET .../API/foomodel/3 /ダウンロード/

戻り値: ...実際のファイルの中身...

また、FooModelでORM以外のSub Resourceファイルを作成することもできます。 resource_uri(リソースの各インスタンスを一意に識別する方法)を定義し、dispatch_detailをオーバーライドして上記のdownload_detailとまったく同じようにする必要があります。

+0

'FileWrapper 'はどこから来たのですか? –

+0

'django.core.servers.basehttpからインポートFileWrapper' – astevanovic

+0

これはクライアントにストリームされた後にファイルハンドルを閉じますか? –

0

のみ変換tastypie FileFieldに上の「URL」を探して、あなたが返すものに属性、およびそれが存在する場合は、そうでなければ、文字列化したオブジェクトを、返すこと返すようにされていましたあなたが気づいたとおり、ファイル名だけです。

ファイルの内容をフィールドとして返す場合は、ファイルのエンコーディングを処理する必要があります。

  • 最もシンプル:あなたは、いくつかの選択肢があり使用CharFieldを、文字列より一般的しかし、機能的に同等
  • にファイルから読み込まれたバイトを変換するbase64モジュールを使用します。どのように知っているカスタムtastypieのシリアライザを書きますファイルオブジェクトをコンテンツの文字列表現に変換する
  • リソースのget_detail関数をオーバーライドして、JSON/XMLシリアル化のオーバーヘッドを避けるために、適切なコンテンツタイプを使用してファイルを提供します。
関連する問題