How do I submit a form provided for HTML source only?

I would like to be able to submit a form in HTML source (string) . In other words, I need at least the ability to generate POST parameters from a string containing the HTML of the form . This is required for unit tests for a Django project. I would like a solution, perhaps

  • Uses only the Python and Django standard library.
  • Allows you to generate parameters from a specific shape if more than one shape is present.
  • Allows me to modify values ​​before submitting.

A solution that returns a form instance (Django) from a given form class is the best. Because it will allow me to use validation. Ideally it will consume the source (which is a string), the form class, and possibly the name of the form, and will return an instance as it did before rendering.

NOTE. I know this is not an easy task, and the benefits are probably not worth the effort. But I'm just wondering how this can be done in a practical and reliable way. If it is possible,

0


source to share


4 answers


You should reread the Django testing framework documentation , in particular the part of testing test views (and forms) with a test client .

Client-client works as a simple web browser and allows you to make inquiries GET

and POST

to your ideas Django. You can read the HTML response, or get the same entity Context

that the template received. Your object Context

should contain the actual instance forms.Form

you are looking for.

As an example, if your URL view /form/

passes context {'myform': forms.Form()}

to the template, you can get it like this:



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)

      

Hope you accomplished what you want without having to mess around with parsing HTML.

Edit . After I re-read the Django docs on Forms, it turns out that forms are immutable. However, this is fine, just create a new instance Form

and submit that; I modified my example code to fit this.

+4


source


Since the Django testing framework does this, I'm not sure what you are asking.

Do you want to test your Django app with a form?

  • In this case, you need to do an initial GET
  • and then the resulting POST

Do you want to write (and test) a Django app that will submit a form to another site?



Here we are testing Django applications with forms.

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 HTML in detail. If it has the correct pattern and has the correct response string, then it must be correct.

+2


source


It's simple ... and difficult at the same time.
Disclaimer: I don't know much about Python and nothing about Django at all ... So I give general, language agnostic advice ... If one of the tips above doesn't work for you, you can do it manually:

  • Load the page with HTML parser, list the forms.
  • If the attribute method

    is POST (case insensitive), get the attribute action

    to get the request url (can be relative).
  • In the form, get tags input

    and select

    . Attributes name

    (or id

    if no name) are the keys of the request parameters. Attributes value

    (empty if absent) - corresponding values.
  • For select

    this value is one of the selected option

    or the display text has no attribute value

    .

These names and values ​​must be URL encoded in GET requests, but not in POST messages.

NTN.

+2


source


Check out the mechanize or he wraps the twill . I think ClientForm will work for you.

0


source







All Articles