I would like to be able to submit a form in an HTML source (string). In other words I need at least the ability to generate POST parameters from a string containing HTML source of the form. This is needed in unit tests for a Django project. I would like a solution that possibly;
我希望能够在HTML源代码中提交表单(字符串)。换句话说,我至少需要能够从包含表单HTML源的字符串生成POST参数。这在Django项目的单元测试中是必需的。我想要一个可能的解决方案;
- Uses only standard Python library and Django.
- Allows parameter generation from a specific form if there is more than one form present.
- Allows me to change the values before submission.
仅使用标准Python库和Django。
如果存在多个表单,则允许从特定表单生成参数。
允许我在提交前更改值。
A solution that returns a (Django) form instance from a given form class is best. Because it would allow me to use validation. Ideally it would consume the source (which is a string), a form class, and optionally a form name and return the instance as it was before rendering.
从给定的表单类返回(Django)表单实例的解决方案是最好的。因为它允许我使用验证。理想情况下,它将使用源(字符串),表单类和可选的表单名称,并在呈现之前返回实例。
NOTE: I am aware this is not an easy task, and probably the gains would hardly justify the effort needed. But I am just curious about how this can be done, in a practical and reliable way. If possible.
注意:我知道这不是一项容易的任务,可能收益很难证明所需的努力是正确的。但我很好奇如何以实际可靠的方式完成这项工作。如果可能的话。
4 个解决方案
#1
4
You should re-read the documentation about Django's testing framework, specifically the part about testing views (and forms) with the test client.
您应该重新阅读有关Django测试框架的文档,特别是关于使用测试客户端测试视图(和表单)的部分。
The test client acts as a simple web browser, and lets you make GET
and POST
requests to your Django views. You can read the response HTML or get the same Context
object the template received. Your Context
object should contain the actual forms.Form
instance you're looking for.
测试客户端充当简单的Web浏览器,允许您对Django视图发出GET和POST请求。您可以阅读响应HTML或获取模板收到的相同Context对象。您的Context对象应该包含您正在寻找的实际forms.Form实例。
As an example, if your view at the URL /form/
passes the context {'myform': forms.Form()}
to the template, you could get to it this way:
例如,如果您在URL / form /上的视图将上下文{'myform':forms.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)
Hopefully that accomplishes what you want, without having to mess with parsing HTML.
希望能够完成你想要的东西,而不必麻烦解析HTML。
Edit: After I re-read the Django docs about Forms, it turns out that forms are immutable. That's okay, though, just create a new Form
instance and submit that; I've changed my code example to match this.
编辑:在我重新阅读关于Forms的Django文档后,结果表明表单是不可变的。但是,没关系,只需创建一个新的Form实例并提交;我已经改变了我的代码示例来匹配它。
#2
2
Since the Django test framework does this, I'm not sure what you're asking.
由于Django测试框架这样做,我不确定你在问什么。
Do you want to test a Django app that has a form?
你想测试一个有表格的Django应用程序吗?
- In which case, you need to do an initial GET
- followed by the resulting POST
在这种情况下,您需要进行初始GET
然后是结果POST
Do you want to write (and test) a Django app that submits a form to another site?
你想编写(并测试)一个将表单提交到另一个站点的Django应用程序吗?
Here's how we test Django apps with forms.
以下是我们如何使用表单测试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")
Note - we don't parse the HTML in detail. If it has the right template and has the right response string, it has to be right.
注意 - 我们不会详细解析HTML。如果它具有正确的模板并且具有正确的响应字符串,那么它必须是正确的。
#3
2
It is simple... and hard at the same time.
Disclaimer: I don't know much about Python and nothing at all about Django... So I give general, language agnostic advices... If one of the above advices doesn't work for you, you might want to do it manually:
这很简单......同时也很难。免责声明:我对Python并不了解,也没有任何关于Django的信息...所以我给出了一般的,与语言无关的建议......如果上述建议之一对你不起作用,你可能想要手动完成:
- Load the page with an HTML parser, list the forms.
- If the
method
attribute is POST (case insensitive), get theaction
attribute to get the URL of the request (can be relative). - In the form, get all
input
andselect
tags. Thename
(orid
if no name) attributes are the keys of the request parameters. Thevalue
attributes (empty if absent) are the corresponding values. - For
select
, the value is the one of the selectedoption
or the displayed text is novalue
attribute.
使用HTML解析器加载页面,列出表单。
如果method属性为POST(不区分大小写),请获取action属性以获取请求的URL(可以是相对的)。
在表单中,获取所有输入和选择标记。名称(或id,如果没有名称)属性是请求参数的键。值属性(如果不存在则为空)是相应的值。
对于select,该值是所选选项之一,或者显示的文本不是value属性。
These names and values must be URL encoded in GET requests, but not in POST ones.
这些名称和值必须在GET请求中进行URL编码,但不能在POST中进行编码。
HTH.
#4
0
Check out mechanize or it's wrapper twill. I think it's ClientForm module will work for you.
检查机械化或它的包装斜纹。我认为它的ClientForm模块将适合您。
#1
4
You should re-read the documentation about Django's testing framework, specifically the part about testing views (and forms) with the test client.
您应该重新阅读有关Django测试框架的文档,特别是关于使用测试客户端测试视图(和表单)的部分。
The test client acts as a simple web browser, and lets you make GET
and POST
requests to your Django views. You can read the response HTML or get the same Context
object the template received. Your Context
object should contain the actual forms.Form
instance you're looking for.
测试客户端充当简单的Web浏览器,允许您对Django视图发出GET和POST请求。您可以阅读响应HTML或获取模板收到的相同Context对象。您的Context对象应该包含您正在寻找的实际forms.Form实例。
As an example, if your view at the URL /form/
passes the context {'myform': forms.Form()}
to the template, you could get to it this way:
例如,如果您在URL / form /上的视图将上下文{'myform':forms.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)
Hopefully that accomplishes what you want, without having to mess with parsing HTML.
希望能够完成你想要的东西,而不必麻烦解析HTML。
Edit: After I re-read the Django docs about Forms, it turns out that forms are immutable. That's okay, though, just create a new Form
instance and submit that; I've changed my code example to match this.
编辑:在我重新阅读关于Forms的Django文档后,结果表明表单是不可变的。但是,没关系,只需创建一个新的Form实例并提交;我已经改变了我的代码示例来匹配它。
#2
2
Since the Django test framework does this, I'm not sure what you're asking.
由于Django测试框架这样做,我不确定你在问什么。
Do you want to test a Django app that has a form?
你想测试一个有表格的Django应用程序吗?
- In which case, you need to do an initial GET
- followed by the resulting POST
在这种情况下,您需要进行初始GET
然后是结果POST
Do you want to write (and test) a Django app that submits a form to another site?
你想编写(并测试)一个将表单提交到另一个站点的Django应用程序吗?
Here's how we test Django apps with forms.
以下是我们如何使用表单测试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")
Note - we don't parse the HTML in detail. If it has the right template and has the right response string, it has to be right.
注意 - 我们不会详细解析HTML。如果它具有正确的模板并且具有正确的响应字符串,那么它必须是正确的。
#3
2
It is simple... and hard at the same time.
Disclaimer: I don't know much about Python and nothing at all about Django... So I give general, language agnostic advices... If one of the above advices doesn't work for you, you might want to do it manually:
这很简单......同时也很难。免责声明:我对Python并不了解,也没有任何关于Django的信息...所以我给出了一般的,与语言无关的建议......如果上述建议之一对你不起作用,你可能想要手动完成:
- Load the page with an HTML parser, list the forms.
- If the
method
attribute is POST (case insensitive), get theaction
attribute to get the URL of the request (can be relative). - In the form, get all
input
andselect
tags. Thename
(orid
if no name) attributes are the keys of the request parameters. Thevalue
attributes (empty if absent) are the corresponding values. - For
select
, the value is the one of the selectedoption
or the displayed text is novalue
attribute.
使用HTML解析器加载页面,列出表单。
如果method属性为POST(不区分大小写),请获取action属性以获取请求的URL(可以是相对的)。
在表单中,获取所有输入和选择标记。名称(或id,如果没有名称)属性是请求参数的键。值属性(如果不存在则为空)是相应的值。
对于select,该值是所选选项之一,或者显示的文本不是value属性。
These names and values must be URL encoded in GET requests, but not in POST ones.
这些名称和值必须在GET请求中进行URL编码,但不能在POST中进行编码。
HTH.
#4
0
Check out mechanize or it's wrapper twill. I think it's ClientForm module will work for you.
检查机械化或它的包装斜纹。我认为它的ClientForm模块将适合您。