Быстрый старт
Эта часть документации показывает, как использовать самые важные части Werkzeug. Она предназначена как отправная точка для разработчиков с базовым пониманием PEP 333 (WSGI) и RFC 2616 (HTTP).
Предупреждение
Убедитесь, что вы импортируете все объекты из тех мест, которые предлагает документация. Теоретически в некоторых ситуациях можно импортировать объекты из разных мест, но это не поддерживается.
Например, MultiDict является членом модуля werkzeug, но внутренне реализован в другом.
Среда WSGI
Среда WSGI содержит всю информацию, которую запрос пользователя передает приложению. Она передается WSGI-приложению, но вы также можете создать словарь WSGI environ с помощью помощника create_environ().
>>> from werkzeug.test import create_environ
>>> environ = create_environ('/foo', 'http://localhost:8080/')
Теперь у нас есть среда для экспериментов:
>>> environ['PATH_INFO'] '/foo' >>> environ['SCRIPT_NAME'] '' >>> environ['SERVER_NAME'] 'localhost'
Обычно никто не хочет работать непосредственно со средой environ, потому что она ограничена байтовыми строками и не предоставляет способов доступа к данным формы, кроме ручного парсинга этих данных.
Ввод запроса
Для доступа к данным запроса объект Request гораздо более удобен. Он оборачивает environ и предоставляет чтение-только доступ к данным оттуда:
>>> from werkzeug.wrappers import Request >>> request = Request(environ)
Теперь вы можете получить доступ к важным переменным, и Werkzeug будет парсить и декодировать их там, где это имеет смысл. По умолчанию кодировка запросов установлена в utf-8, но вы можете изменить её, создав подкласс Request.
>>> request.path u'/foo' >>> request.script_root u'' >>> request.host 'localhost:8080' >>> request.url 'http://localhost:8080/foo'
Мы также можем узнать, какой HTTP-метод был использован для запроса:
>>> request.method 'GET'
Таким образом, мы также можем получить доступ к аргументам URL (строке запроса) и данным, которые были переданы в запросе POST/PUT.
В целях тестирования мы можем создать объект запроса из предоставленных данных, используя метод from_values():
>>> from cStringIO import StringIO >>> data = "name=this+is+encoded+form+data&another_key=another+one" >>> request = Request.from_values(query_string='foo=bar&blah=blafasel', ... content_length=len(data), input_stream=StringIO(data), ... content_type='application/x-www-form-urlencoded', ... method='POST') ... >>> request.method 'POST'
Теперь мы можем легко получить доступ к параметрам URL:
>>> request.args.keys() ['blah', 'foo'] >>> request.args['blah'] u'blafasel'
То же самое относится к предоставленным данным формы:
>>> request.form['name'] u'this is encoded form data'
Обработка загруженных файлов не намного сложнее, как видно из этого примера:
def store_file(request):
file = request.files.get('my_file')
if file:
file.save('/where/to/store/the/file.txt')
else:
handle_the_error()
Файлы представлены как объекты FileStorage, которые предоставляют некоторые общие операции для работы с ними.
К заголовкам запроса можно получить доступ, используя атрибут headers:
>>> request.headers['Content-Length'] '54' >>> request.headers['Content-Type'] 'application/x-www-form-urlencoded'
Ключи заголовков, конечно, нечувствительны к регистру.
Парсинг заголовков
Есть и ещё. Werkzeug предоставляет удобный доступ к часто используемым HTTP-заголовкам и другим данным запроса.
Давайте создадим объект запроса со всеми данными, которые обычно передает веб-браузер, чтобы поэкспериментировать с ним:
>>> environ = create_environ() >>> environ.update( ... HTTP_USER_AGENT='Mozilla/5.0 (Macintosh; U; Mac OS X 10.5; en-US; ) Firefox/3.1', ... HTTP_ACCEPT='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', ... HTTP_ACCEPT_LANGUAGE='de-at,en-us;q=0.8,en;q=0.5', ... HTTP_ACCEPT_ENCODING='gzip,deflate', ... HTTP_ACCEPT_CHARSET='ISO-8859-1,utf-8;q=0.7,*;q=0.7', ... HTTP_IF_MODIFIED_SINCE='Fri, 20 Feb 2009 10:10:25 GMT', ... HTTP_IF_NONE_MATCH='"e51c9-1e5d-46356dc86c640"', ... HTTP_CACHE_CONTROL='max-age=0' ... ) ... >>> request = Request(environ)
Давайте начнём с самого бесполезного заголовка: user agent:
>>> request.user_agent.browser 'firefox' >>> request.user_agent.platform 'macos' >>> request.user_agent.version '3.1' >>> request.user_agent.language 'en-US'
Более полезным заголовком является accept header. С помощью этого заголовка браузер сообщает веб-приложению, какие типы MIME он может обработать и насколько хорошо. Все accept-заголовки отсортированы по качеству, лучшим элементом является первый:
>>> request.accept_mimetypes.best 'text/html' >>> 'application/xhtml+xml' in request.accept_mimetypes True >>> print request.accept_mimetypes["application/json"] 0.8
То же самое работает для языков:
>>> request.accept_languages.best 'de-at' >>> request.accept_languages.values() ['de-at', 'en-us', 'en']
И, конечно же, кодировки и наборы символов:
>>> 'gzip' in request.accept_encodings True >>> request.accept_charsets.best 'ISO-8859-1' >>> 'utf-8' in request.accept_charsets True
Нормализация доступна, поэтому вы можете безопасно использовать альтернативные формы для проверки вхождения:
>>> 'UTF8' in request.accept_charsets True >>> 'de_AT' in request.accept_languages True
Теги E-tag и другие условные заголовки также доступны в обработанном виде:
>>> request.if_modified_since datetime.datetime(2009, 2, 20, 10, 10, 25) >>> request.if_none_match <ETags '"e51c9-1e5d-46356dc86c640"'> >>> request.cache_control <RequestCacheControl 'max-age=0'> >>> request.cache_control.max_age 0 >>> 'e51c9-1e5d-46356dc86c640' in request.if_none_match True
Ответы
Объекты ответа — это противоположность объектам запроса. Они используются для отправки данных обратно клиенту. В реальности объекты ответа — это не более чем улучшенные WSGI-приложения.
Поэтому вы не возвращаете объекты ответа из своего WSGI-приложения, а вызываете его как WSGI-приложение внутри своего WSGI-приложения и возвращаете значение этого вызова.
Представьте ваше стандартное WSGI-приложение «Hello World»:
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return ['Hello World!']
С объектами ответа оно будет выглядеть так:
from werkzeug.wrappers import Response
def application(environ, start_response):
response = Response('Hello World!')
return response(environ, start_response)
Также, в отличие от объектов запроса, объекты ответа предназначены для модификации. Вот что вы можете с ними сделать:
>>> from werkzeug.wrappers import Response
>>> response = Response("Hello World!")
>>> response.headers['content-type']
'text/plain; charset=utf-8'
>>> response.data
'Hello World!'
>>> response.headers['content-length'] = len(response.data)
Вы можете изменить статус ответа аналогичным образом. Либо только код, либо указать сообщение:
>>> response.status '200 OK' >>> response.status = '404 Not Found' >>> response.status_code 404 >>> response.status_code = 400 >>> response.status '400 BAD REQUEST'
Как видите, атрибуты работают в обоих направлениях. Вы можете установить как status, так и status_code, и изменения будут отражены в другом.
Также общие заголовки представлены как атрибуты или методами для их установки/получения:
>>> response.content_length 12 >>> from datetime import datetime >>> response.date = datetime(2009, 2, 20, 17, 42, 51) >>> response.headers['Date'] 'Fri, 20 Feb 2009 17:42:51 GMT'
Поскольку теги etag могут быть слабыми или сильными, существуют методы для их установки:
>>> response.set_etag("12345-abcd")
>>> response.headers['etag']
'"12345-abcd"'
>>> response.get_etag()
('12345-abcd', False)
>>> response.set_etag("12345-abcd", weak=True)
>>> response.get_etag()
('12345-abcd', True)
Некоторые заголовки доступны как изменяемые структуры. Например, большинство заголовков Content- представляют собой множества значений:
>>> response.content_language.add('en-us')
>>> response.content_language.add('en')
>>> response.headers['Content-Language']
'en-us, en'
И здесь это также работает в обоих направлениях:
>>> response.headers['Content-Language'] = 'de-AT, de' >>> response.content_language HeaderSet(['de-AT', 'de'])
Таким же образом можно установить заголовки аутентификации:
>>> response.www_authenticate.set_basic("My protected resource")
>>> response.headers['www-authenticate']
'Basic realm="My protected resource"'
Также можно установить куки:
>>> response.set_cookie('name', 'value')
>>> response.headers['Set-Cookie']
'name=value; Path=/'
>>> response.set_cookie('name2', 'value2')
Если заголовки появляются несколько раз, вы можете использовать метод getlist(), чтобы получить все значения для заголовка:
>>> response.headers.getlist('Set-Cookie')
['name=value; Path=/', 'name2=value2; Path=/']
Наконец, если вы установили все условные значения, вы можете сделать ответ условным относительно запроса. Это означает, что если запрос может гарантировать, что у него уже есть информация, никакие данные, кроме заголовков, не отправляются по сети, что экономит трафик. Для этого вы должны установить по крайней мере etag (который используется для сравнения) и заголовок даты, а затем вызвать make_conditional с объектом запроса.
Ответ модифицируется соответственно (изменён код состояния, удалён тело ответа, удалены заголовки сущности).
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/1.0.x/quickstart/