JSONを使用してPOST Djangoフレームワークを使用して簡単なRESTリクエストを作成する方法を教えてくれる人を歓迎します。私はチュートリアルでこれの例をどこにも見ませんか?
これが、POSTするRoleモデルオブジェクトです。これは、データベースに追加したい新しいロールになりますが、500エラーが表示されます。
{
"name": "Manager",
"description": "someone who manages"
}
Bashターミナルプロンプトでのcurlリクエストは次のとおりです。
curl -X POST -H "Content-Type: application/json" -d '[
{
"name": "Manager",
"description": "someone who manages"
}]'
http://localhost:8000/lakesShoreProperties/role
URL
http://localhost:8000/lakesShoreProperties/roles
GET要求で動作し、データベース内のすべてのロールをプルダウンできますが、新しいロールを作成することはできません。権限が設定されていません。 views.pyで標準ビューを使用しています
class RoleDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Role.objects.all()
serializer_class = RoleSerializer
format = None
class RoleList(generics.ListCreateAPIView):
queryset = Role.objects.all()
serializer_class = RoleSerializer
format = None
このアプリのurls.py
では、関連するURL-ビューマッピングが正しい:
url(r'^roles/$', views.RoleList.as_view()),
url(r'^role/(?P<pk>[0-9]+)/$', views.RoleDetail.as_view()),
エラーメッセージ:
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
ここで何が起こっており、これに対する修正は何ですか?ローカルホストはクロスサイトリクエストですか? @csrf_exempt
をRoleDetail
とRoleList
に追加しましたが、何も変わらないようです。このデコレータをクラスに追加することもできますか、それともメソッドに追加する必要がありますか? @csrf_exempt
デコレートを追加すると、私のエラーは次のようになります。
Request Method: POST
Request URL: http://127.0.0.1:8000/lakeshoreProperties/roles/
Django Version: 1.5.1
Exception Type: AttributeError
Exception Value:
'function' object has no attribute 'as_view'
次に、アプリ全体でCSRFを無効にし、次のメッセージを受け取りました。
{"non_field_errors":["Invalid data"]}私が知っているJSONオブジェクトが有効なjsonである場合。それはフィールド以外のエラーですが、私はここで立ち往生しています。
まあ、それは私のJSONが有効ではなかったことが判明しましたか?
{
"name": "admin",
"description": "someone who administrates"
}
対
[
{
"name": "admin",
"description": "someone who administrates"
}
]
括弧[]で囲むと、POST要求が失敗します。しかし、jsonlint.comバリデータを使用すると、両方のjsonオブジェクトが検証されます。
Update:問題は、バックエンドではなく、PostManでPOSTを送信することでした。 https://stackoverflow.com/a/17508420/203312 を参照してください
おそらく、リクエストとともにCSRFトークンを送信する必要があります。チェックアウト https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#csrf-ajax
更新:既にCSRFを免除しようとしているので、これが役立つかもしれません(Django使用しているバージョンによって異なります): https://stackoverflow.com/a/14379073/977931
CSRFは、Django REST Frameworkでデフォルトで免除されています。したがって、curl POST要求は正常に機能します。 POSTMANがcsrfトークンをCookiesで検出した場合、含まれているため、POSTMAN要求呼び出しはCSRFを誤って返しました。これは、Cookieをクリーンアップすることで解決できます。
これは、REST Framework設定からのものです。settings.py
ファイルでは、REST_FRAMEWORK
には次のものが必要です。
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
}
これにより、csrf認証の代わりにトークン認証を使用するようにREST Frameworkが設定されます。許可をAllowAny
に設定することにより、目的の場所のみを認証できます。
わかりました、もちろん今私は言ったことを取り戻します。 CSRFは意図したとおりに機能します。
POSTMANというPOSTプラグインを使用してchromeリクエストを作成していました。 CSRFが有効になっていると、私のPOST要求は失敗します。
しかし、カールPOSTリクエストを使用して
curl -X POST -H "Content-Type: application/json" -d '
{
"name": "Manager",
"description": "someone who manages"
}' http://127.0.0.1:8000/lakeshoreProperties/roles/
正常に動作します...中かっこを削除する必要がありました(つまり、[])。ロールの 's'の後にスラッシュがあることを確認しました。つまり、roles /、csrf enabledはエラーをスローしませんでした。
POSTMANを使用して呼び出すこととcurlを使用することの違いはわかりませんが、POSTMANはWebブラウザーで実行されるのが最大の違いです。つまり、クラスRoleList全体でcsrfを無効にしましたが、Curlでは同じ要求が1つ機能しますが、POSTMANでは失敗します。
現在のステータスに関する最新情報を提供し、いくつかの回答をまとめるには:
相互作用しているAPIと同じコンテキスト内で行われるAJAX要求は、通常
SessionAuthentication
を使用します。これにより、ユーザーがログインすると、AJAXリクエストはすべて、Webサイトの他の部分で使用されるのと同じセッションベースの認証を使用して認証されます。通信しているAPIとは異なるサイトで作成されたAJAXリクエストは、通常、
TokenAuthentication
などの非セッションベースの認証スキームを使用する必要があります。
したがって、SessionAuthentication
をTokenAuthentication
に置き換えることを推奨する回答で問題を解決できますが、必ずしも完全に正しいとは限りません。
これらのタイプの攻撃から保護するには、2つのことを行う必要があります。
GET
、HEAD
、OPTIONS
などの「安全な」HTTP操作を使用して、サーバー側の状態を変更できないようにしてください。
POST
、PUT
、PATCH
、DELETE
などの「安全でない」HTTP操作には、常に有効なCSRFトークンが必要であることを確認してください。SessionAuthentication
を使用している場合、すべてのPOST
、PUT
、PATCH
、またはDELETE
操作に有効なCSRFトークンを含める必要があります。 。AJAXリクエストを行うには、=で説明されているように、HTTPヘッダーにCSRFトークンを含める必要があります。 Django documentation。
したがって、たとえば this answer が示唆するように、csrfがヘッダーに含まれていることが重要です。
あなたが言ったようにあなたのURLは
http://localhost:8000/lakesShoreProperties/roles
Postmanにはlocalhostに関する問題があります。代わりにPOSTを127.0.0.1:8000/your-api/endpoint
に送信すると、私にとってはうまくいきませんでした。
AllowAny
パーミッションを設定していて、csrfの問題に直面している場合
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny'
]
}
次に、settings.py
は問題を解決します
REST_SESSION_LOGIN = False