.. _forms:

.. currentmodule:: grab.ext.form

================
Работа с формами
================

Автоматическая обработка форм
=============================

Если запрошенный документ содержит форму, вы можете заполнить её поля с помощью метода :meth:`~FormExtension.set_input` и отослать методом :meth:`~FormExtension.submit`. Значения для полей, которые вы не заполнили явно, будут вычислены автоматически. В первую, очередь это касается hidden-полей, но для select, checkbox, radio полей Grab также попытается подставить какое-либо значение. Все методы работают с формой, которая выбрана по-умолчанию. Если в документе несколько форм, то будет выбрана та форма, в которой больше всего полей. В методах `set_input_*` автоматический выбор работает несколько по иному, выбирается та форма, которая содержит указанное поле.

Простейший пример поиска на яндексе::

    >>> g = Grab()
    >>> g.go('http://ya.ru')
    <grab.response.Response object at 0x1a51ad0>
    >>> g.set_input('text', 'grab python')
    >>> g.submit()
    <grab.response.Response object at 0x1ad41d0>
    >>> g.xpath('//li[@class="b-serp-item"]//a/@href')
    'http://packages.python.org/grab/'

Форма, выбранная по-умолчанию, доступна через аттрибут `form`. Это объект `lxml.etree.Element` с дополнительными свойствами, подробнее вы можете прочитать в `lxml мануале <http://lxml.de/lxmlhtml.html#forms>`_.

Если по какой-либо причине вы не можете использовать метод `set_input` для задания значения элемента по его имени, попробуйте методы: `set_input_by_id` или универсальный `set_input_by_xpath`.

Смотрите полный список доступных методов в :ref:`extensions_form`.

Отправка формы
==============

Как было уже сказано выше, при отправке формы методом `submit` значения полей, которые в не задали явно, вычисляются автоматически. Это избавляет от рутинной обработки hidden-полей. Также автоматически вычисляется нужные метод HTTP-запроса (POST или GET), нужная кодировка данных (`www/url-encoded` или `multipart/form-data`), полный адрес формы (аттрибут `action`). У метода `submit` есть несколько полезных аргументов:

* `submit_name` - позволяет "нажать" нужный вам submit-элементов (полезно, если их несколько)
* `make_request` - передав False в этом аргументе вы отлючите автоматическую посылку данных формы. Все параметры запроса будут подготовлены в точности, как описано выше, но запрос не будет сгенерирован. Вы можете подправить его параметры по своему вкусу и уже затем отослать его на сервер.
* `url` - переопределение адреса, куда будет направлен запрос с данными формы
* `extra_post` - словарь с данными полей, которые переопределят автоматически вычисленные значения.

Отправка файлов
===============

Для отправки файлов используйте специальный класс :class:`~grab.base.UploadFile`. Его конструктор принимает единственный элемент - путь к файлу. Вы можете использовать объект класса `UploadFile` в методе :meth:`~FormExtension.submit`::

    g.set_input('file', UploadFile('/path/to/file'))
    g.submit()
