HTMLソースのみを指定してフォームを送信するにはどうすればよいですか?
-
19-08-2019 - |
質問
HTMLソース(文字列)でフォームを送信できるようにしたい。言い換えれば、少なくともフォームのHTMLソースを含む文字列からPOSTパラメーターを生成する機能が必要です。これは、Djangoプロジェクトの単体テストで必要です。可能性のある解決策が欲しい;
- 標準のPythonライブラリとDjangoのみを使用します。
- 複数のフォームが存在する場合、特定のフォームからのパラメーター生成を許可します。
- 送信前に値を変更することを許可します。
特定のフォームクラスから(Django)フォームインスタンスを返すソリューションが最適です。検証を使用できるからです。理想的には、ソース(文字列)、フォームクラス、およびオプションでフォーム名を消費し、レンダリング前のインスタンスを返します。
注:これは簡単な作業ではないことは承知していますが、おそらくこの利益が必要な努力を正当化することはほとんどないでしょう。しかし、実用的で信頼できる方法で、これをどのように行うことができるかについて、私は興味があります。可能であれば。
解決
Djangoのテストフレームワークに関するドキュメントを再度お読みください。特に、を使用してビュー(およびフォーム)をテストする部分テストクライアント。
テストクライアントは単純なWebブラウザーとして機能し、Djangoビューに対してGET
およびPOST
リクエストを行うことができます。応答HTMLを読むか、テンプレートが受け取った同じContext
オブジェクトを取得できます。 forms.Form
オブジェクトには、探している実際の/form/
インスタンスが含まれている必要があります。
例として、URL {'myform': forms.Form()}
のビューがコンテキストForm
をテンプレートに渡す場合、次のようにして取得できます。
from django.test.client import Client
c = Client()
# request the web page:
response = c.get('/form/')
# get the Form object:
form = response.context['myform']
form_data = form.cleaned_data
my_form_data = {} # put your filled-out data in here...
form_data.update(my_form_data)
# submit the form back to the web page:
new_form = forms.Form(form_data)
if new_form.is_valid():
c.post('/form/', new_form.cleaned_data)
うまくいけば、HTMLの解析を台無しにすることなく、あなたが望むものを達成できます。
編集:フォームに関するDjangoのドキュメントを読み直したところ、フォームは不変であることがわかりました。ただし、新しい<=>インスタンスを作成して送信するだけです。これに合わせてコード例を変更しました。
他のヒント
Djangoテストフレームワークがこれを行うため、あなたが何を求めているのかわかりません。
フォームを持つDjangoアプリをテストしますか?
- その場合、最初のGETを行う必要があります
- 結果のPOSTが続きます
フォームを別のサイトに送信するDjangoアプリを作成(およびテスト)しますか?
フォームを使用してDjangoアプリをテストする方法は次のとおりです。
class Test_HTML_Change_User( django.test.TestCase ):
fixtures = [ 'auth.json', 'someApp.json' ]
def test_chg_user_1( self ):
self.client.login( username='this', password='this' )
response= self.client.get( "/support/html/user/2/change/" )
self.assertEquals( 200, response.status_code )
self.assertTemplateUsed( response, "someApp/user.html")
def test_chg_user( self ):
self.client.login( username='this', password='this' )
# The truly fussy would redo the test_chg_user_1 test here
response= self.client.post(
"/support/html/user/2/change/",
{'web_services': 'P',
'username':'olduser',
'first_name':'asdf',
'last_name':'asdf',
'email':'asdf@asdf.com',
'password1':'passw0rd',
'password2':'passw0rd',} )
self.assertRedirects(response, "/support/html/user/2/" )
response= self.client.get( "/support/html/user/2/" )
self.assertContains( response, "<h2>Users: Details for", status_code=200 )
self.assertContains( response, "olduser" )
self.assertTemplateUsed( response, "someApp/user_detail.html")
注-HTMLの詳細は解析しません。適切なテンプレートと適切な応答文字列がある場合は、正しくなければなりません。
それは簡単です...同時に難しいです。
免責事項:私はPythonについてあまり知らず、Djangoについてはまったく知りません...だから、一般的な言語にとらわれないアドバイスをします...
上記のアドバイスのいずれかがうまくいかない場合は、手動で行うことをお勧めします。
- HTMLパーサーでページをロードし、フォームをリストします。
-
method
属性がPOST(大文字と小文字を区別しない)の場合、action
属性を取得して、リクエストのURLを取得します(相対的な場合もあります)。 - フォームで、すべての
input
およびselect
タグを取得します。name
(または名前がない場合はid
)属性は、要求パラメーターのキーです。value
属性(存在しない場合は空)は対応する値です。 -
option
の場合、値は選択された<=>の1つであるか、表示されたテキストは<=>属性ではありません。
これらの名前と値は、GETリクエストではURLエンコードされている必要がありますが、POSTリクエストではエンコードされていません。
HTH。
mechanize またはそのラッパーツイル。 ClientForm モジュールが機能すると思います。