Быстрый старт
Эта часть документации демонстрирует, как использовать важнейшие части Werkzeug. Она предназначена как отправная точка для разработчиков с базовым пониманием PEP 3333 (WSGI) и RFC 2616 (HTTP).
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 будет парсить и декодировать их, где это необходимо.
>>> request.path '/foo' >>> request.script_root '' >>> request.host 'localhost:8080' >>> request.url 'http://localhost:8080/foo'
Мы также можем узнать, какой HTTP метод был использован для запроса:
>>> request.method 'GET'
Таким образом, мы также можем получить доступ к аргументам URL (строке запроса) и данным, переданным в запросах POST/PUT.
Для тестирования мы можем создать объект запроса из предоставленных данных, используя from_values() метод:
>>> from io 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'] 'blafasel'
То же самое касается предоставленных данных формы:
>>> request.form['name'] '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_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)
С помощью заголовка 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, tzinfo=datetime.timezone.utc) >>> 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, timezone >>> response.date = datetime(2009, 2, 20, 17, 42, 51, tzinfo=timezone.utc) >>> 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 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/latest/quickstart/