import cStringIO import ClientForm def html_form_to_post_dict(content, base_uri): ''' content: HTML string. Return a dictionary mapping form names to a dictionary with input values. {'form_name': {'input1: 'default text', ...} } Example usage in a django unittest. url=reverse('myapp.views.foo.edit', kwargs={'foo_id': foo_id}) response=self.client.get(url) # client: django.test.Client post=html_form_to_post_dict(response.content, url)['foo'] post['text']='my input' response=self.client.post(url, post) assert response.status_code==302, 'No redirect after POST. Form might contain errors?' foo=Foo.objects.get(id=foo.id) assert foo.text=='my input', u'Foo not updated: text: %s' % foo.text Needs ClientForm from: http://wwwsearch.sourceforge.net/ClientForm/ ''' fd=cStringIO.StringIO(content) forms={} for form in ClientForm.ParseFile(fd, base_uri, backwards_compat=False): old=forms.get(form.name) assert not old, 'Broken HTML: two forms with the same name %s %s' % ( old.name, form.name) values={} for control in form.controls: if isinstance(control, (ClientForm.IgnoreControl, ClientForm.SubmitControl)): continue old=values.get(control.name) assert not old, 'Broken HTML: form %s contains the input name %s twice.' % ( form.name, control) values[control.name]=control.value forms[form.name]=values return forms