ブラウザ拡張

「オーバーロードされたPOSTには、議論の余地のない2つの用途があります。1つ目は、PUTまたはDELETEをサポートしていないWebブラウザなどのクライアントのためにHTTPの統一インターフェースを*シミュレート*することです」

RESTful Webサービス、Leonard Richardson&Sam Ruby。

ブラウザブルAPIを機能させるため、REST frameworkが提供する必要があるブラウザ拡張がいくつかあります。

バージョン3.3.0以降、これらはajax-formライブラリを使用してJavaScriptで有効になっています。

ブラウザベースのPUT、DELETEなど...

AJAXフォームライブラリは、HTMLフォームでのブラウザベースのPUTDELETE、およびその他のメソッドをサポートしています。

ライブラリを含めた後、次のようにフォームのdata-method属性を使用します。

<form action="/" data-method="PUT">
    <input name='foo'/>
    ...
</form>

3.3.0より前は、このサポートはJavaScriptベースではなくサーバーサイドでした。メソッドオーバーロードスタイル(Ruby on Railsで使用されている)は、リクエストの解析で微妙な問題が発生するため、サポートされなくなりました。

ブラウザベースの非フォームコンテンツの送信

JSONなどのコンテントタイプのブラウザベースの送信は、data-override='content-type'およびdata-override='content'属性を持つフォームフィールドを使用するAJAXフォームライブラリでサポートされています。

例えば

    <form action="/">
        <input data-override='content-type' value='application/json' type='hidden'/>
        <textarea data-override='content'>{}</textarea>
        <input type="submit"/>
    </form>

3.3.0より前は、このサポートはJavaScriptベースではなくサーバーサイドでした。

URLベースのフォーマットサフィックス

REST frameworkは、?format=jsonスタイルのURLパラメータを使用できます。これは、ビューからどのコンテントタイプを返すかを決定するための便利なショートカットになります。

この動作は、URL_FORMAT_OVERRIDE設定を使用して制御されます。

HTTPヘッダーベースのメソッドオーバーライド

バージョン3.3.0より前は、リクエストメソッドをオーバーライドするためにセミ拡張ヘッダーX-HTTP-Method-Overrideがサポートされていました。この動作はコアではなくなりましたが、必要に応じてミドルウェアを使用して追加できます。

例えば

METHOD_OVERRIDE_HEADER = 'HTTP_X_HTTP_METHOD_OVERRIDE'

class MethodOverrideMiddleware:

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.method == 'POST' and METHOD_OVERRIDE_HEADER in request.META:
            request.method = request.META[METHOD_OVERRIDE_HEADER]
        return self.get_response(request)

URLベースのAcceptヘッダー

バージョン3.3.0までは、REST frameworkには?accept=application/jsonスタイルのURLパラメータの組み込みサポートが含まれており、Acceptヘッダーをオーバーライドすることができました。

コンテンツネゴシエーションAPIの導入以来、この動作はコアには含まれなくなりましたが、必要に応じてカスタムコンテンツネゴシエーションクラスを使用して追加できます。

例えば

class AcceptQueryParamOverride()
    def get_accept_list(self, request):
       header = request.META.get('HTTP_ACCEPT', '*/*')
       header = request.query_params.get('_accept', header)
       return [token.strip() for token in header.split(',')]

HTML5はPUTおよびDELETEフォームをサポートしていませんか?

いいえ。かつてはPUTおよびDELETEフォームをサポートすることを目的としていましたが、後に仕様から削除されましたPUTDELETEのサポート、およびフォームエンコードデータ以外のコンテントタイプのサポート方法については、現在も議論が続いています