Быстрый старт
Эта часть документации демонстрирует, как использовать самые важные части 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)
Начнём с самого бесполезного заголовка: пользовательского агента:
>>> request.user_agent.browser 'firefox' >>> request.user_agent.platform 'macos' >>> request.user_agent.version '3.1' >>> request.user_agent.language 'en-US'
Более полезный заголовок — это заголовок accept. С этим заголовком браузер информирует веб-приложение о том, какие 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-приложение «Привет, мир»:
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/0.15.x/quickstart/