<commit_before>Form Handling in Pylons
+++++++++++++++++++++++

Background
==========

When a user submits a form on a website the data is submitted to the URL specified in the ``action`` attribute of the ``<form>`` tag. The data can be submitted either via HTTP ``GET`` or ``POST`` as specified by the ``method`` attribute of the ``<form>`` tag. If no action is specified the data is submitted to the current URL without the query string so you should always specify an action.

If the form contains a file upload field such as ``<input type="file" name="file" />`` then the HTML ``<form>`` tag must also specify ``enctype="multipart/form-data"`` and ``method`` must be ``POST``.


Getting Started
===============

First `install Pylons </install/>`_ and follow the `Getting Started Guide </docs/getting_started.html>`_ so that you have a running ``HelloWorld`` application with a ``hello`` controller available at http://localhost:5000/hello served with the ``--reload`` option.

Add two actions that looks like this:

.. code-block:: Python
    # in the controller

    def form(self):  
        return render_response('/form.myt')  

    def email(self):
        return Response('Your email is: %s' % request.params['email'])
    
Add a new template called ``form.myt`` in the ``templates`` directory that contains the following:

.. code-block:: Hypertext

    <form name="test" method="GET" action="/hello/email">
    Email Address: <input type="text" name="email" />
                   <input type="submit" name="submit" value="Submit" /> 
    </form>

If the server is still running (see the Getting Started Guide) you can visit http://localhost:5000/hello/form and you will see the form. Try entering the email address ``<EMAIL>`` and clicking Submit. The URL should change to http://localhost:5000/hello/email?email=test%40example.com and you should see the text ``Your email is <EMAIL>``.

In Pylons all form variables can be accessed from the ``request.params`` object which behaves like a dictionary. The keys are the names of the fields in the form and the value is a string with all the characters entity decoded. For example note how the ``@`` character was converted by the browser to ``%40`` in the URL and was converted back ready for use in ``request.params``.
 
.. Note:: ``request`` is actually a ``WSGIRequest`` object `documented here <http://pythonpaste.org/class-paste.wsgiwrappers.WSGIRequest.html#params>`_ and ``request.params`` is a ``MultiDict`` with `documentation here <http://pythonpaste.org/class-paste.util.multidict.MultiDict.html>`_.

If you have two fields with the same name in the form then using the dictionary interface will return the first string. You can get all the strings returned as a list by using the ``.getall()`` method. If you only expect one value and want to enforce this you should use ``.getone()`` which raises an error if more than one value with the same name is submitted. 

By default if a field is submitted without a value, the dictionary interface returns an empty string. This means that using ``.get(key, default)`` on ``request.params`` will only return a default if the value was not present in the form.


POST vs GET and the Re-Submitted Data Problem
---------------------------------------------
<commit_msg>[svn] Formatting tweaks.<commit_after>Form Handling in Pylons
+++++++++++++++++++++++

Background
==========

When a user submits a form on a website the data is submitted to the URL specified in the ``action`` attribute of the ``<form>`` tag. The data can be submitted either via HTTP ``GET`` or ``POST`` as specified by the ``method`` attribute of the ``<form>`` tag. If no action is specified the data is submitted to the current URL without the query string so you should always specify an action.

If the form contains a file upload field such as ``<input type="file" name="file" />`` then the HTML ``<form>`` tag must also specify ``enctype="multipart/form-data"`` and ``method`` must be ``POST``.


Getting Started
===============

First `install Pylons </install/>`_ and follow the `Getting Started Guide </docs/getting_started.html>`_ so that you have a running ``HelloWorld`` application with a ``hello`` controller available at http://localhost:5000/hello served with the ``--reload`` option.

Add two actions that looks like this:

.. code-block:: Python
    
    # in the controller

    def form(self):  
        return render_response('/form.myt')  

    def email(self):
        return Response('Your email is: %s' % request.params['email'])

Add a new template called ``form.myt`` in the ``templates`` directory that contains the following:

.. code-block:: Hypertext

    <form name="test" method="GET" action="/hello/email">
    Email Address: <input type="text" name="email" />
                   <input type="submit" name="submit" value="Submit" /> 
    </form>

If the server is still running (see the Getting Started Guide) you can visit http://localhost:5000/hello/form and you will see the form. Try entering the email address ``<EMAIL>`` and clicking Submit. The URL should change to http://localhost:5000/hello/email?email=test%40example.com and you should see the text ``Your email is <EMAIL>``.

In Pylons all form variables can be accessed from the ``request.params`` object which behaves like a dictionary. The keys are the names of the fields in the form and the value is a string with all the characters entity decoded. For example note how the ``@`` character was converted by the browser to ``%40`` in the URL and was converted back ready for use in ``request.params``.
 
.. Note:: ``request`` is actually a ``WSGIRequest`` object `documented here <http://pythonpaste.org/class-paste.wsgiwrappers.WSGIRequest.html#params>`_ and ``request.params`` is a ``MultiDict`` with `documentation here <http://pythonpaste.org/class-paste.util.multidict.MultiDict.html>`_.

If you have two fields with the same name in the form then using the dictionary interface will return the first string. You can get all the strings returned as a list by using the ``.getall()`` method. If you only expect one value and want to enforce this you should use ``.getone()`` which raises an error if more than one value with the same name is submitted. 

By default if a field is submitted without a value, the dictionary interface returns an empty string. This means that using ``.get(key, default)`` on ``request.params`` will only return a default if the value was not present in the form.


POST vs GET and the Re-Submitted Data Problem
---------------------------------------------

{'fraction_non_alphanumeric': 0.12849756690997566, 'fraction_numerical': 0.004866180048661801, 'mean_word_length': 3.948833709556057, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3356710', 'n_tokens_mistral': 1745, 'n_tokens_neox': 1659, 'n_words': 868}