1

私はtastypieでAPIを作成しているモデルを持っています。手動で管理しているファイルへのパスを格納するフィールドがあります(FileFieldユーザーがファイルをアップロードしていないため、使用していません)。モデルの要点は次のとおりです。

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
        """
        ...

これが私のおいしい設定です:

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'))

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

ありがとうございました

4

2 に答える 2

4

最初に、APIを介してファイルを公開する方法をURLスキームで決定します。fileや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 / filename.ext'、...}

GET ... / api / foomodel / 3 / download /

戻り値:...実際のファイルの内容...

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

于 2012-02-26T15:31:07.867 に答える
0

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

ファイルの内容をフィールドとして返したい場合は、ファイルのエンコーディングを処理する必要があります。いくつかのオプションがあります。

  • 最も簡単:モジュールを使用CharFieldして使用base64し、ファイルから読み取ったバイトを文字列に変換します
  • より一般的ですが機能的に同等です:Fileオブジェクトをその内容の文字列表現に変換する方法を知っているカスタムのtastypieシリアライザーを作成します
  • get_detailJSON / XMLシリアル化のオーバーヘッドを回避するために、適切なコンテンツタイプを使用してファイルのみを提供するように、リソースの機能をオーバーライドします。
于 2012-02-26T15:27:16.463 に答える