parsers.py

パーサー

マシンがやり取りするWebサービスは、単純なフォームよりも複雑なデータを送信するため、フォームエンコードよりも構造化された形式を使用してデータを送信する傾向があります。

— Malcom Tredinnick, Django developers group

REST frameworkには、さまざまなメディアタイプの要求を受け入れることができる、多数の組み込みパーサークラスが含まれています。また、独自のカスタムパーサーを定義することもサポートされており、APIが受け入れるメディアタイプを柔軟に設計できます。

パーサーの決定方法

ビューの有効なパーサーのセットは、常にクラスのリストとして定義されます。 `request.data`にアクセスすると、REST frameworkは受信リクエストの`Content-Type`ヘッダーを調べ、リクエストコンテンツの解析に使用するパーサーを決定します。


:クライアントアプリケーションを開発する際は、HTTPリクエストでデータを送信する際に`Content-Type`ヘッダーを設定していることを常に確認してください。

コンテンツタイプを設定しないと、ほとんどのクライアントはデフォルトで `'application/x-www-form-urlencoded'`を使用しますが、これは意図したものではない場合があります。

例として、.ajax()メソッドを使用してjQueryで`json`エンコードされたデータを送信する場合は、`contentType:'application/json'`設定を含めるようにしてください。


パーサーの設定

デフォルトのパーサーセットは、`DEFAULT_PARSER_CLASSES`設定を使用してグローバルに設定できます。たとえば、次の設定では、JSONまたはフォームデータのデフォルトではなく、`JSON`コンテンツのリクエストのみが許可されます。

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
    ]
}

`APIView`クラスベースのビューを使用して、個々のビューまたはビューセットに使用されるパーサーを設定することもできます。

from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    """
    A view that can accept POST requests with JSON content.
    """
    parser_classes = [JSONParser]

    def post(self, request, format=None):
        return Response({'received data': request.data})

または、関数ベースのビューで`@api_view`デコレータを使用している場合。

from rest_framework.decorators import api_view
from rest_framework.decorators import parser_classes
from rest_framework.parsers import JSONParser

@api_view(['POST'])
@parser_classes([JSONParser])
def example_view(request, format=None):
    """
    A view that can accept POST requests with JSON content.
    """
    return Response({'received data': request.data})

APIリファレンス

JSONParser

`JSON`リクエストコンテンツを解析します。 `request.data`には、データの辞書が設定されます。

.media_type:`application/json`

FormParser

HTMLフォームコンテンツを解析します。 `request.data`には、データの`QueryDict`が設定されます。

HTMLフォームデータを完全にサポートするには、通常、`FormParser`と`MultiPartParser`の両方を使用する必要があります。

.media_type:`application/x-www-form-urlencoded`

MultiPartParser

ファイルのアップロードをサポートする、multipart HTMLフォームコンテンツを解析します。 `request.data`と`request.FILES`には、それぞれ`QueryDict`と`MultiValueDict`が設定されます。

HTMLフォームデータを完全にサポートするには、通常、`FormParser`と`MultiPartParser`の両方を使用する必要があります。

.media_type:`multipart/form-data`

FileUploadParser

生のファイルアップロードコンテンツを解析します。 `request.data`プロパティは、アップロードされたファイルを含む単一のキー`'file'`を持つ辞書になります。

`FileUploadParser`で使用されるビューが`filename` URLキーワード引数で呼び出された場合、その引数はファイル名として使用されます。

`filename` URLキーワード引数なしで呼び出された場合、クライアントは`Content-Disposition` HTTPヘッダーでファイル名を設定する必要があります。たとえば、`Content-Disposition: attachment; filename=upload.jpg`です。

.media_type:`*/*`

注記
  • `FileUploadParser`は、ファイルを生のデータリクエストとしてアップロードできるネイティブクライアントで使用するためのものです。Webベースのアップロード、またはmultipartアップロードをサポートするネイティブクライアントの場合は、代わりに`MultiPartParser`を使用する必要があります。
  • このパーサーの`media_type`はすべてのコンテンツタイプに一致するため、`FileUploadParser`は一般に、APIビューに設定されている唯一のパーサーである必要があります。
  • `FileUploadParser`は、Djangoの標準`FILE_UPLOAD_HANDLERS`設定と`request.upload_handlers`属性を尊重します。詳細については、Djangoのドキュメントを参照してください。
基本的な使用例
# views.py
class FileUploadView(views.APIView):
    parser_classes = [FileUploadParser]

    def put(self, request, filename, format=None):
        file_obj = request.data['file']
        # ...
        # do some stuff with uploaded file
        # ...
        return Response(status=204)

# urls.py
urlpatterns = [
    # ...
    re_path(r'^upload/(?P<filename>[^/]+)$', FileUploadView.as_view())
]

カスタムパーサー

カスタムパーサーを実装するには、`BaseParser`をオーバーライドし、`.media_type`プロパティを設定し、`.parse(self, stream, media_type, parser_context)`メソッドを実装する必要があります。

このメソッドは、`request.data`プロパティの設定に使用されるデータを返す必要があります。

`.parse()`に渡される引数は次のとおりです。

stream

リクエストの本文を表すストリームのようなオブジェクト。

media_type

オプション。指定されている場合、これは受信リクエストコンテンツのメディアタイプです。

リクエストの`Content-Type:`ヘッダーに応じて、これはレンダラーの`media_type`属性よりも具体的であり、メディアタイプパラメータを含めることができます。たとえば、`"text/plain; charset=utf-8"`です。

parser_context

オプション。指定されている場合、この引数は、リクエストコンテンツの解析に必要な追加のコンテキストを含む辞書になります。

デフォルトでは、これには次のキーが含まれます:`view`、`request`、`args`、`kwargs`。

以下は、`request.data`プロパティにリクエストの本文を表す文字列を設定する、プレーンテキストパーサーの例です。

class PlainTextParser(BaseParser):
    """
    Plain text parser.
    """
    media_type = 'text/plain'

    def parse(self, stream, media_type=None, parser_context=None):
        """
        Simply return a string representing the body of the request.
        """
        return stream.read()

サードパーティパッケージ

以下のサードパーティパッケージも利用可能です。

YAML

REST framework YAMLは、YAMLの解析とレンダリングのサポートを提供します。以前はREST frameworkパッケージに直接含まれていましたが、現在はサードパーティパッケージとしてサポートされています。

インストールと設定

pipを使用してインストールします。

$ pip install djangorestframework-yaml

REST frameworkの設定を変更します。

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework_yaml.parsers.YAMLParser',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_yaml.renderers.YAMLRenderer',
    ],
}

XML

REST Framework XMLは、単純な非公式XML形式を提供します。以前はREST frameworkパッケージに直接含まれていましたが、現在はサードパーティパッケージとしてサポートされています。

インストールと設定

pipを使用してインストールします。

$ pip install djangorestframework-xml

REST frameworkの設定を変更します。

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework_xml.parsers.XMLParser',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework_xml.renderers.XMLRenderer',
    ],
}

MessagePack

MessagePackは、高速で効率的なバイナリシリアライゼーション形式です。Juan Riazaは、REST frameworkにMessagePackレンダラーとパーサーのサポートを提供するdjangorestframework-msgpackパッケージを保守しています。

CamelCase JSON

djangorestframework-camel-caseは、REST frameworkにキャメルケースJSONレンダラーとパーサーを提供します。これにより、シリアライザーはPythonスタイルのアンダースコア付きフィールド名を使用できますが、APIではJavascriptスタイルのキャメルケースフィールド名として公開されます。Vitaly Babiyによって保守されています。