ジャンゴフォーム


HTML フォームは、Web サイトのインタラクティブ性の古典的な方法です。 この章では、Django を使用してユーザーが送信したフォーム データを処理する方法を紹介します。


HTTPリクエスト

HTTPプロトコルは「リクエスト-リプライ」方式で動作します。クライアントはリクエストを送信するときに、リクエストにデータを追加できます。リクエストを解析することで、サーバーはクライアントから送信されたデータを取得し、URL に基づいて特定のサービスを提供できます。

GET メソッド

ユーザーリクエストを受け取るために、前のプロジェクトで search.py​​ ファイルを作成しました:

# -*- coding: utf-8 -*-

from django.http import HttpResponse
from django.shortcuts import render_to_response

# 表单
def search_form(request):
	return render_to_response('search_form.html')

# 接收请求数据
def search(request):  
	request.encoding='utf-8'
	if 'q' in request.GET:
		message = '你搜索的内容为: ' + request.GET['q'].encode('utf-8')
	else:
		message = '你提交了空表单'
	return HttpResponse(message)

テンプレートディレクトリに search_form.html フォームを追加します テンプレート:

<html>
<head>
	<meta charset="utf-8" /> 
    <title>Search - w3cschool.cc</title>
</head>
<body>
    <form action="/search/" method="get">
        <input type="text" name="q">
        <input type="submit" value="Search">
    </form>
</body>
</html>

urls.py ルールは次のように変更されますフォーム:

from django.conf.urls import *
from HelloWorld.view import hello
from HelloWorld.testdb import testdb
from HelloWorld import search

urlpatterns = patterns("",
	('^hello/$', hello),
	('^testdb/$', testdb),
	(r'^search-form/$', search.search_form),
	(r'^search/$', search.search),
)

アクセスアドレス: http://192.168.45.3:8000/search-form/ で検索すると、結果は次のようになります:

1044.jpg

1045.jpg

POSTメソッド

上記のGETメソッドを使用しました。ビュー表示とリクエスト処理は 2 つの機能に分かれています。

データを送信する場合は、POST メソッドがより一般的に使用されます。以下ではこのメソッドを使用し、URL と処理関数を使用してビューの表示とリクエストの処理を同時に行います。

tmplate に post.html を作成します。

<html>
<head>
	<meta charset="utf-8" /> 
    <title>Search - w3cschool.cc</title>
</head>
<body>
	<form action="/search-post/" method="post">
		{% csrf_token %}
		<input type="text" name="q">
		<input type="submit" value="Submit">
	</form>

	<p>{{ rlt }}</p>
</body>
</html>

テンプレートの最後に、テーブル処理結果の場所を予約するための rlt マークを追加します。

フォームの後ろには {% csrf_token %} タグもあります。 csrf の正式名は、Cross Site Request Forgery です。これは、偽装された送信リクエストを防ぐために Django が提供する機能です。 POST メソッドを使用して送信されたフォームには、このタグが必要です。

HelloWorld ディレクトリに新しい search2.py ファイルを作成し、search_post 関数を使用して POST リクエストを処理します:

# -*- coding: utf-8 -*-

from django.shortcuts import render
from django.core.context_processors import csrf

# 接收POST请求数据
def search_post(request):
	ctx ={}
	ctx.update(csrf(request))
	if request.POST:
		ctx['rlt'] = request.POST['q']
	return render(request, "post.html", ctx)

urls.py ルールは次の形式に変更されます:

from django.conf.urls import *
from HelloWorld.view import hello
from HelloWorld.testdb import testdb
from HelloWorld import search
from HelloWorld import search2

urlpatterns = patterns("",
	('^hello/$', hello),
	('^testdb/$', testdb),
	(r'^search-form/$', search.search_form),
	(r'^search/$', search.search),
	(r'^search-post/$', search2.search_post),
)

http://192.168.45.3 にアクセスします。 :8000/search-post/ 表示される結果は次のとおりです:

1046.jpg

上記の例を完了すると、ディレクトリ構造は次のようになります:

HelloWorld
|-- HelloWorld
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- models.pyc
|   |-- search.py
|   |-- search.pyc
|   |-- search2.py
|   |-- search2.pyc
|   |-- settings.py
|   |-- settings.pyc
|   |-- testdb.py
|   |-- testdb.pyc
|   |-- urls.py
|   |-- urls.pyc
|   |-- view.py
|   |-- view.pyc
|   |-- wsgi.py
|   `-- wsgi.pyc
|-- TestModel
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- admin.py
|   |-- models.py
|   |-- models.pyc
|   |-- tests.py
|   `-- views.py
|-- manage.py
`-- templates
    |-- base.html
    |-- hello.html
    |-- post.html
    `-- search_form.html

3 directories, 29 files

Request オブジェクト

各ビュー関数の最初のパラメーターは、次のように HttpRequest オブジェクトです。次の hello() 関数:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello world")

HttpRequest オブジェクトには、現在のリクエスト URL に関する情報が含まれています:

META 利用可能なすべての HTTP ヘッダー情報を含む辞書。 例: user は django.contrib です。 auth.models.User オブジェクト。現在ログインしているユーザーを表します。

Properties

Description

path

フルリクエストされたページへのパス (ドメイン名を除く) - 例: "/hello/"。

method

リクエストで使用されるHTTPメソッドの文字列表現。すべて大文字で表現します。例:

if request.method == 'GET':
do_something()
elif request.method == 'POST':
do_something_else()

GET

すべてのHTTP GETパラメータが含まれます辞書のようなオブジェクト。 QueryDict のドキュメントを参照してください。

投稿

すべての HTTP POST パラメータを含む辞書のようなオブジェクト。 QueryDict のドキュメントを参照してください。

サーバーが空の POST リクエストを受信する可能性もあります。つまり、フォームは HTTP POST メソッドを通じてリクエストを送信しますが、フォーム内にデータは必要ありません。したがって、ステートメント if request.POST を使用して HTTP POST メソッドを使用するかどうかを決定することはできません。代わりに、if request.method == "POST" を使用してください (この表のメソッド属性を参照)。

注: POST にはファイルのアップロード情報は含まれません。 FILES 属性を参照してください。

REQUEST

便宜上、この属性は POST 属性と GET 属性のコレクションですが、最初に POST 属性を探してから、GET 属性を探します。 PHP の $_REQUEST から学びましょう。

たとえば、GET = {"name": "john"} および POST = {"age": '34'} の場合、REQUEST["name"] の値は "john"、REQUEST["age" になります。 ] 値は「34」です。

これら 2 つの属性はより明示的で、記述されたコードが理解しやすいため、GET と POST を使用することを強くお勧めします。

COOKIES

すべての Cookie を含む標準の Python 辞書オブジェクト。キーと値は両方とも文字列です。 Cookie の詳細な説明については、第 12 章を参照してください。

FILES

アップロードされたすべてのファイルを含む辞書のようなオブジェクト。 FILES の各キーは、<input type="file" name="" /> タグの name 属性の値でもあり、次の 3 つのキーが含まれます。

    filename: Python 文字列で表されるアップロードされたファイルの名前
  • content-type: アップロードされたファイルのコンテンツタイプ
  • content: アップロードされたファイルの元のコンテンツ
  • 注: のみリクエストメソッドが POST で、リクエストページの <form> に enctype="multipart/form-data" 属性がある場合、FILES にデータのみが含まれる場合。それ以外の場合、FILES は空の辞書です。

    CONTENT_LENGTH
  • CONTENT_TYPE
  • QUERY_STRING: 未解析の生のクエリ文字列
  • REMOTE_ADDR: クライアントIPアドレス
  • TE _HOST: クライアントのホスト名
  • SERVER_NAME : サーバーのホストname
  • SERVER_PORT: サーバーポート
  • META これらのヘッダーには、キーとして HTTP_ が接頭辞として付けられます。例:

    HTTP_ACCEPT_ENCODING
  • HTTP_ACCEPT_LANGUAGE
  • HTTP_HOST: クライアントのホストヘッダーによって送信された HTTP情報
  • HTTP_REFERER: 参照ページ
  • HTTP_USER_AGENT: クライアントのユーザーエージェント文字列
  • HTTP_X_BENDER: X-Bender ヘッダー情報

アクセスしているユーザーが現在ログインしていない場合、ユーザーは django.contrib.auth.models.AnonymousUser のインスタンスに初期化されます。

ユーザーがログインしているかどうかは、ユーザーの is_authenticated() メソッドを通じて識別できます:


if request.user.is_authenticated():
    # Do something for logged-in users.
else:
    # Do something for anonymous users.

この属性は、Django の AuthenticationMiddleware がアクティブ化されている場合にのみ使用できます

session

および書き込み可能属性 (現在のセッションを表す辞書オブジェクト)。このプロパティは、Django のセッション サポートがアクティブ化されている場合にのみ使用できます。 第 12 章を参照してください。

raw_post_data

未加工の HTTP POST データ。 高度な処理に便利です。

Request オブジェクトにはいくつかの便利なメソッドもあります。

メソッド Description
__getitem__(key) GET/POST のキー値を返し、最初に POST を受け取り、次に GET を受け取ります。キーが存在しない場合は KeyError をスローします。
これは、辞書構文を使用して HttpRequest オブジェクトにアクセスする方法です。
たとえば、request["foo"] は、request.POST["foo"] の次に request.GET["foo"] と同等です。
has_key() request.GETまたはrequest.POSTにパラメータで指定されたKeyが含まれているかどうかを確認します。
get_full_path()クエリ文字列を含むリクエストパスを返します。たとえば、「/music/bands/the_beatles/?print=true」
is_secure() リクエストが安全であれば、True を返します。つまり、HTTPS リクエストが発行されます。

QueryDict オブジェクト

HttpRequest オブジェクトの GET 属性と POST 属性は、django.http.QueryDict クラスのインスタンスです。

QueryDict は辞書のようなカスタム クラスで、単一のキーが複数の値に対応する状況を処理するために使用されます。

QueryDict はすべての標準辞書メソッドを実装します。また、いくつかのユニークなメソッドも含まれています:

キーが複数の値に対応する場合、 get( ) は最後の値を返します。 パラメータにはQueryDictまたは標準辞書を指定できます。標準辞書の update メソッドとは異なり、このメソッドは辞書項目を置換するのではなく追加します。 は、単一の値を使用する標準辞書の items() メソッドとは少し異なります。 __getitem__():は、単一値論理__getitem__():
MethodDescription

__getitem__

は標準辞書とは少し異なります。つまり、キーが複数の値に対応する場合、 __getitem__( ) は最後の値を返します。

__setitem__

キーの値リスト(Pythonリスト)を指定するパラメータを設定します。注: 変更可能な QueryDict オブジェクト (つまり、copy() によって生成された QueryDict オブジェクトのコピー) でのみ呼び出すことができます

update()

>>> q = QueryDict('a=1')

>>> q = q.copy() # to make it mutable

>>> q.update({'a': '2'})

>>> q.getlist('a')

 ['1', '2']

>>> q['a'] # returns the last

['2']

items()

>>> q = QueryDict('a=1&a=2&a=3')

>>> q.items()

[('a', '3')]

values()

を使用する標準辞書のvalues()メソッドとは少し異なります。

さらに、QueryDict には、次の表に示すように、いくつかのメソッドもあります。

Description オブジェクトのコピーを返します。内部実装は Python 標準ライブラリ .deepcopy() を使用したコピーです。コピーは変更可能です。つまり、コピーの値は変更できます。 パラメータキーに対応するすべての値をPythonリストとして返します。キーが存在しない場合は、空のリストが返されます。何らかのリストを返すことが保証されています。 key の値を list_ に設定します (__setitem__() とは異なります)。 key に関連付けられた内部リストに項目を追加します。 は、単一の値の代わりにリストを受け入れるという点で setdefault とは少し異なりますパラメータとして。 は items() とは少し異なり、キーのすべての値をリストとして返します。例: return クエリ文字列形式でフォーマットされた文字列 (例: "a=2&b=3&b=5")。
copy()

getlist(key)

setlist(key,list_)

appendlist(key 、 item)

setlistdefault(key, list)

lists()

>>> q = QueryDict('a=1&a=2&a=3')

>>> q.lists()

[('a', ['1', '2', '3'])]

urlencode()