◀ 4.

djangoでGETとPOSTパラメータ受け取る方法

▶
この記事の要点
  • GET(URL の ?key=value)は request.GET、フォームの POST は request.POST から取り出す
  • request.GET['key'] はキーがないと MultiValueDictKeyError。request.GET.get('key', 既定値) が安全
  • 同じ名前で複数の値(チェックボックスなど)は getlist() で受け取る
  • 値は常に文字列。数値として使うなら変換と入力チェックが必要
  • JSON を POST された場合は request.POST は空。json.loads(request.body) で読む
  • POST フォームには {% csrf_token %} が必須。ないと 403 になる

Django の関数ベースビュー(FBV)で、GET パラメータと POST パラメータを受け取る方法をまとめます。クラスベースビューでの受け取り方は関連する別記事を参照してください。

GET

val1 = request.GET['val1']

http://localhost:8000/search/?val1=abc にアクセスすると、val1 に文字列 "abc" が入ります。

POST

val1 = request.POST['val1']

フォームの <input name="val1"> に入力された値が入ります。name 属性の値がキーになります。

実践的な書き方(キーがない場合に備える)

request.GET / request.POST は QueryDict という辞書に似たオブジェクトです。[] で存在しないキーを指定すると MultiValueDictKeyError が発生するため、実際には get() で既定値を指定するのが定番です。

from django.shortcuts import render

def search(request):
    keyword = request.GET.get('q', '')          # なければ空文字
    page = request.GET.get('page', '1')         # 値は常に文字列
    try:
        page = int(page)
    except ValueError:
        page = 1
    return render(request, 'search.html', {'keyword': keyword, 'page': page})

GET と POST を 1 つのビューで処理する

from django.shortcuts import render, redirect

def contact(request):
    if request.method == 'POST':
        name = request.POST.get('name', '').strip()
        message = request.POST.get('message', '').strip()
        if not name:
            return render(request, 'contact.html', {'error': '名前は必須です'})
        # 保存やメール送信などの処理
        return redirect('contact_done')   # 二重送信防止のためリダイレクト
    return render(request, 'contact.html')
<form method="post" action="">
  {% csrf_token %}
  <input type="text" name="name">
  <textarea name="message"></textarea>
  <button type="submit">送信</button>
</form>

複数の値を受け取る(getlist)

チェックボックスや ?tag=a&tag=b のように同じ名前の値が複数送られる場合、get() は最後の 1 つしか返しません。全部受け取るには getlist() を使います。

tags = request.GET.getlist('tag')        # ['a', 'b']
colors = request.POST.getlist('color')   # 未選択なら []

受け取り方の早見表

送られ方受け取り方
URL のクエリ文字列 ?key=valuerequest.GET.get('key')
HTML フォームの POSTrequest.POST.get('key')
同じキーで複数の値request.GET.getlist('key') / request.POST.getlist('key')
JSON 本文(fetch / Ajax)json.loads(request.body)
ファイル(enctype="multipart/form-data")request.FILES.get('key')
URL のパスの一部 /items/5/urls.py の path('items/<int:item_id>/', ...) で定義し、ビューの引数 item_id で受け取る

JSON を受け取る例

import json
from django.http import JsonResponse

def api_create(request):
    if request.method != 'POST':
        return JsonResponse({'error': 'POST only'}, status=405)
    try:
        data = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({'error': 'invalid JSON'}, status=400)
    name = data.get('name')
    return JsonResponse({'name': name})

よくある落とし穴

  • MultiValueDictKeyError: [] で存在しないキーを読んだ。フォームの name 属性のつづり違いや、未選択のチェックボックス(値が送信されない)が典型。get() を使う
  • 403 CSRF verification failed: POST フォームに {% csrf_token %} がない、または Ajax で CSRF トークンをヘッダーに付けていない
  • POST なのに request.POST が空: 送信側が JSON(Content-Type: application/json)で送っている。request.body を読む
  • 値が文字列: "10" と 10 は別物。比較や計算の前に int() などで変換し、変換失敗に備える
  • QueryDict は変更できない: request.GET['x'] = 'y' はエラー。変更したいなら request.GET.copy() で複製する
  • 入力チェックを手書きしすぎない: 項目が多いなら Django の Form クラス(forms.Form)を使うと、型変換・必須チェック・エラー表示をまとめて扱える

確認方法

  • ビューの中で print(request.method, request.GET, request.POST) を一時的に書くと、runserver を動かしている端末に受け取った内容が表示される
  • ブラウザの開発者ツールの「ネットワーク」タブで、実際に送られたパラメータ(クエリ文字列・フォームデータ・JSON)を確認する

関連

子ページ

子ページはありません

同階層のページ
  1. クラスベースビュー(主流)の作り方とviewの分割
  2. 関数ベースビューの作り方とviewの分割
  3. URLディスパッチャー(ルーティング処理)
  4. GETとPOSTパラメータ受け取り
  5. クラスベースビューでGET/POSTリクエストの受け取り方
  6. クラスベースビューでテンプレートに値を渡す方法
  7. ビューでリダイレクト
  8. cookieの値の設定と取得
  9. HTTPステータスコードの返し方