• en
  • Language: ru
  • Documentation version: 1.1.x

Обновление до более новых версий

Сама Flask меняется, как меняется со временем любое программное обеспечение. Большинство изменений - приятные, такие, когда вам не нужно ничего менять в своем коде, чтобы извлечь выгоду из нового релиза.

Однако время от времени происходят изменения, которые требуют внесения некоторых изменений в ваш код, или изменения, которые позволяют вам улучшить качество собственного кода, воспользовавшись новыми возможностями Flask.

В этом разделе документации перечислены все изменения во Flask от выпуска к выпуску и то, как вы можете изменить свой код, чтобы обновление прошло безболезненно.

Используйте команду pip для обновления существующей установки Flask, указав параметр --upgrade:

$ pip install --upgrade Flask

Версия 0.12

Изменения в send_file

filename больше не выводится автоматически из файлоподобных объектов. Это означает, что следующий код больше не будет автоматически иметь поддержку X-Sendfile, генерацию etag или угадывание MIME-типа:

response = send_file(open('/path/to/file.txt'))

Любой из следующих вариантов функционально эквивалентен:

fname = '/path/to/file.txt'

# Just pass the filepath directly
response = send_file(fname)

# Set the MIME-type and ETag explicitly
response = send_file(open(fname), mimetype='text/plain')
response.set_etag(...)

# Set `attachment_filename` for MIME-type guessing
# ETag still needs to be manually set
response = send_file(open(fname), attachment_filename=fname)
response.set_etag(...)

Причина в том, что некоторые файлоподобные объекты имеют недопустимый или даже вводящий в заблуждение атрибут name. Молчаливое проглатывание ошибок в таких случаях не является удовлетворительным решением.

Кроме того, было ограничено возвращение по умолчанию к application/octet-stream. Если Flask не может угадать один или пользователь не предоставил его, функция завершается неудачно, если не была предоставлена информация об имени файла.

Версия 0.11

0.11 - странный релиз в цикле выпуска Flask, потому что он должен был стать релизом 1.0. Однако из-за длительной подготовки к релизу мы решили сначала выпустить релиз 0.11, убрав некоторые изменения, чтобы облегчить переход. Если вы следили за основной веткой, которая была 1.0, вы можете увидеть некоторые неожиданные изменения.

Если вы отслеживали мастер-ветку, вы заметите, что flask --app теперь удалено. Вам нужно использовать переменную окружения для указания приложения.

Отладка

В версии Flask 0.11 из приложений Flask удален атрибут debug_log_format. Вместо этого новая конфигурация LOGGER_HANDLER_POLICY может быть использована для отключения обработчиков журналов по умолчанию, а также для настройки пользовательских обработчиков журналов.

Обработка ошибок

Изменено поведение обработчиков ошибок. Раньше приоритет обработчиков был основан на порядке оформления/вызова errorhandler() и register_error_handler() соответственно. Теперь приоритет имеет иерархия наследования, и обработчики для более конкретных классов исключений выполняются вместо более общих. Подробности см. в разделе Обработчики ошибок.

Попытка зарегистрировать обработчик на экземпляре теперь вызывает ошибку ValueError.

Примечание

Раньше существовала логическая ошибка, позволяющая регистрировать обработчики только для исключений экземпляров. Это было непреднамеренно и просто неправильно, и поэтому было заменено на предусмотренное поведение регистрации обработчиков только с использованием классов исключений и кодов ошибок HTTP.

Шаблонизация

Функция render_template_string() изменила автоэскейп переменных шаблона по умолчанию. Это лучше соответствует поведению render_template().

Импорт расширений

Импорты расширений вида flask.ext.foo устарели, следует использовать flask_foo.

Старая форма по-прежнему работает, но Flask будет выдавать flask.exthook.ExtDeprecationWarning для каждого расширения, которое вы импортируете старым способом. Мы также предоставляем утилиту миграции под названием flask-ext-migrate, которая должна автоматически переписывать ваши импорты для этого.

Версия 0.10

Самым большим изменением с 0.9 на 0.10 является то, что формат сериализации cookie изменился с pickle на специализированный формат JSON. Это изменение было сделано для того, чтобы избежать ущерба, который может нанести злоумышленник в случае утечки секретного ключа. При обновлении вы заметите два основных изменения: все сессии, которые были выпущены до обновления, становятся недействительными, и вы можете хранить в сессии только ограниченное количество типов. Новые сессии по своему дизайну более ограничены и позволяют хранить только JSON с несколькими небольшими расширениями для кортежей и строк с HTML-разметкой.

Чтобы не нарушать чужие сессии, можно продолжать использовать старую систему сессий, используя расширение Flask-OldSessions.

Flask также начал хранить объект flask.g в контексте приложения вместо контекста запроса. Это изменение должно быть прозрачным для вас, но оно означает, что теперь вы можете хранить вещи в объекте g, когда еще нет контекста запроса, но есть контекст приложения. Старый атрибут flask.Flask.request_globals_class был переименован в flask.Flask.app_ctx_globals_class.

Версия 0.9

Поведение возврата кортежей из функции было упрощено. Если вы возвращаете кортеж, он больше не определяет аргументы для создаваемого объекта ответа, теперь это всегда кортеж в форме (response, status, headers), где должен быть предоставлен хотя бы один элемент. Если вы зависите от старого поведения, вы можете легко добавить его, создав подкласс Flask:

class TraditionalFlask(Flask):
    def make_response(self, rv):
        if isinstance(rv, tuple):
            return self.response_class(*rv)
        return Flask.make_response(self, rv)

Если вы поддерживаете расширение, которое ранее использовало _request_ctx_stack, пожалуйста, рассмотрите возможность перехода на _app_ctx_stack, если это имеет смысл для вашего расширения. Например, стек контекста приложения имеет смысл для расширений, которые подключаются к базам данных. Использование стека контекста приложений вместо стека контекста запросов позволит расширениям легче справляться с ситуациями, не связанными с запросами.

Версия 0.8

Flask представил новую систему интерфейса сессий. Мы также заметили, что существует коллизия имен между модулем flask.session, реализующим сессии, и flask.session, который является глобальным объектом сессии. С этим введением мы перенесли детали реализации системы сессий в новый модуль под названием flask.sessions. Если вы использовали ранее недокументированную поддержку сессий, мы настоятельно рекомендуем вам перейти на новый модуль.

Если были отправлены недопустимые JSON-данные, Flask теперь будет поднимать исключение BadRequest вместо того, чтобы позволять всплывать стандартному ValueError. Преимуществом этого является то, что вам больше не придется обрабатывать эту ошибку, чтобы избежать появления внутренней ошибки сервера для пользователя. Если в прошлом вы отлавливали эту ошибку в явном виде как ValueError, вам придется изменить это.

Из-за ошибки в тестовом клиенте Flask 0.7 не срабатывали обработчики разрыва, когда тестовый клиент использовался в операторе with. С тех пор это было исправлено, но может потребоваться внести некоторые изменения в ваши наборы тестов, если вы полагались на такое поведение.

Версия 0.7

В версии Flask 0.7 мы значительно очистили внутреннюю кодовую базу и внесли некоторые обратно несовместимые изменения, которые облегчают реализацию больших приложений с помощью Flask. Поскольку мы хотим сделать обновление как можно более простым, мы попытались решить проблемы, возникающие в связи с этими изменениями, предоставив скрипт, который может облегчить переход.

Сценарий сканирует все ваше приложение и генерирует унифицированный diff с изменениями, которые, по его мнению, безопасны для применения. Однако, поскольку это автоматизированный инструмент, он не сможет найти все случаи использования и может пропустить некоторые. Мы разместили множество предупреждений об устаревании по всему приложению, чтобы облегчить поиск фрагментов кода, которые он не смог обновить.

Мы настоятельно рекомендуем вам вручную просмотреть сгенерированный файл исправлений и применить только те фрагменты, которые выглядят хорошо.

Если вы используете git в качестве системы контроля версий для вашего проекта, мы рекомендуем применять патч с помощью path -p1 < patchfile.diff, а затем использовать функцию интерактивной фиксации, чтобы применять только те фрагменты, которые выглядят хорошо.

Чтобы применить сценарий обновления, сделайте следующее:

  1. Скачать скрипт: flask-07-upgrade.py

  2. Запустите его в каталоге вашего приложения:

    $ python flask-07-upgrade.py > patchfile.diff
    
  3. Просмотрите созданный файл исправлений.

  4. Примените патч:

    $ patch -p1 < patchfile.diff
    
  5. Если вы использовали папки шаблонов для каждого модуля, вам необходимо переместить некоторые шаблоны. Раньше, если у вас была папка с именем templates рядом с чертежом с именем admin, неявный путь к шаблону автоматически становился admin/index.html для файла шаблона с именем templates/index.html. Теперь это не так. Теперь вам нужно назвать шаблон templates/admin/index.html. Инструмент не определит этого, поэтому вам придется сделать это самостоятельно.

Обратите внимание, что начиная с Python 2.7 предупреждения об износе по умолчанию отключены. Для того чтобы увидеть предупреждения об износе, которые могут быть выданы, необходимо включить их с помощью модуля warnings.

Если вы работаете с windows и вам не хватает утилиты командной строки patch, вы можете получить ее в составе различных сред выполнения Unix для windows, включая cygwin, msysgit или ming32. Также системы контроля исходных текстов, такие как svn, hg или git, имеют встроенную поддержку для применения унифицированных различий, генерируемых этим инструментом. Для получения дополнительной информации обратитесь к руководству вашей системы контроля версий.

Ошибка в локализации запросов

Из-за ошибки в предыдущих реализациях локальные прокси запроса теперь поднимают RuntimeError вместо AttributeError, когда они отвязаны. Если раньше вы ловили эти исключения с помощью AttributeError, то теперь вы должны ловить их с помощью RuntimeError.

Кроме того, функция send_file() теперь выдает предупреждения об устаревании, если вы зависите от функциональности, которая будет удалена во Flask 0.11. Ранее можно было использовать etags и mimetypes при передаче объектов файлов. Это было ненадежно и вызывало проблемы в некоторых настройках. Если вы получаете предупреждение об устаревании, убедитесь, что обновили свое приложение для работы с именами файлов, либо отключите прикрепление etag и прикрепляйте их самостоятельно.

Старый код:

return send_file(my_file_object)
return send_file(my_file_object)

Новый код:

return send_file(my_file_object, add_etags=False)

Модернизация до новой системы обработки разрывов

Мы оптимизировали поведение обратных вызовов для обработки запросов. Для вещей, которые изменяют ответ, декораторы after_request() продолжают работать, как и ожидалось, но для вещей, которые абсолютно должны происходить в конце запроса, мы ввели новый декоратор teardown_request(). К сожалению, это изменение также изменило работу after-request в условиях ошибки. Он не пропускается последовательно, если происходят исключения, тогда как раньше он мог быть вызван дважды, чтобы убедиться, что он выполняется в конце запроса.

Если у вас есть код подключения к базе данных, который выглядит следующим образом:

@app.after_request
def after_request(response):
    g.db.close()
    return response

Теперь вам рекомендуется использовать это вместо:

@app.teardown_request
def after_request(exception):
    if hasattr(g, 'db'):
        g.db.close()

С другой стороны, это изменение значительно улучшает внутренний поток кода и облегчает настройку диспетчеризации и обработки ошибок. Это значительно облегчает написание модульных тестов, так как вы можете предотвратить закрытие соединений с базой данных на некоторое время. Вы можете воспользоваться тем, что обратные вызовы разрыва вызываются, когда контекст ответа удаляется из стека, поэтому тест может запросить базу данных после обработки запроса:

with app.test_client() as client:
    resp = client.get('/')
    # g.db is still bound if there is such a thing

# and here it's gone

Присоединение обработчика ошибок вручную

Хотя все еще можно прикреплять обработчики ошибок к Flask.error_handlers, делать это не рекомендуется и фактически устарело. В целом, мы больше не рекомендуем прикреплять пользовательские обработчики ошибок через присваивания к базовому словарю из-за более сложной внутренней обработки для поддержки произвольных классов исключений и чертежей. Смотрите Flask.errorhandler() для получения дополнительной информации.

Правильное обновление заключается в изменении этого:

app.error_handlers[403] = handle_error

В этом:

app.register_error_handler(403, handle_error)

В качестве альтернативы можно просто прикрепить функцию с помощью декоратора:

@app.errorhandler(403)
def handle_error(e):
    ...

(Обратите внимание, что register_error_handler() является новым в версии Flask 0.7)

Поддержка чертежей

Черновики заменяют предыдущую концепцию «Модули» во Flask. Они обеспечивают лучшую семантику для различных функций и лучше работают с большими приложениями. Предоставленный скрипт обновления должен автоматически обновлять ваши приложения, но в некоторых случаях обновление может не произойти. Что изменилось?

  • Чертежам нужны явные имена. Модули имели схему автоматического угадывания имени, в которой короткое имя модуля бралось из последней части импортируемого модуля. Сценарий обновления пытается угадать это имя, но может потерпеть неудачу, так как эта информация может измениться во время выполнения.

  • Черновики имеют обратное поведение для url_for(). Раньше .foo говорил url_for(), что он должен искать конечную точку foo в приложении. Теперь это означает «относительно текущего модуля». Скрипт будет инвертировать все вызовы url_for() автоматически для вас. Он будет делать это очень охотно, поэтому в коде могут появиться ненужные лидирующие точки, если вы не используете модули.

  • Черновики не предоставляют автоматически статические папки. Они также больше не будут автоматически экспортировать шаблоны из папки с названием templates рядом с их местоположением, однако это можно включить из конструктора. То же самое со статическими файлами: если вы хотите продолжать обслуживать статические файлы, вам нужно явно указать конструктору путь к статической папке (который может быть относительным к пути модуля блюпринта).

  • Рендеринг шаблонов был упрощен. Теперь чертежи могут предоставлять папки шаблонов, которые добавляются к общему пути поиска шаблонов. Это означает, что вам нужно добавить еще одну подпапку с именем чертежа в эту папку, если вы хотите, чтобы в качестве имени шаблона было blueprintname/template.html.

Если вы продолжаете использовать объект Module, который устарел, Flask восстановит прежнее поведение настолько хорошо, насколько это возможно. Однако мы настоятельно рекомендуем перейти на новые чертежи, поскольку они предоставляют множество полезных улучшений, таких как возможность прикреплять чертеж несколько раз, специфичные для чертежей обработчики ошибок и многое другое.

Версия 0.6

Flask 0.6 поставляется с несовместимым с предыдущей версией изменением, которое влияет на порядок вызова обработчиков после запроса. Ранее они вызывались в порядке регистрации, теперь же они вызываются в обратном порядке. Это изменение было сделано для того, чтобы Flask вел себя в большей степени так, как ожидали люди и как другие системы обрабатывают запросы до и после регистрации. Если вы зависите от порядка выполнения функций пост-запроса, обязательно измените этот порядок.

Еще одно изменение, нарушающее обратную совместимость, заключается в том, что контекстные процессоры больше не будут переопределять значения, переданные непосредственно в функцию рендеринга шаблона. Если, например, request является переменной, переданной непосредственно в шаблон, контекстный процессор по умолчанию не будет переопределять ее с текущим объектом запроса. Это облегчает последующее расширение контекстных процессоров для введения дополнительных переменных без нарушения существующего шаблона, не ожидающего их.

Версия 0.5

Flask 0.5 - первый релиз, который поставляется в виде пакета Python, а не отдельного модуля. Было проведено несколько внутренних рефакторингов, так что если вы зависите от недокументированных внутренних деталей, вам, вероятно, придется адаптировать импорт.

Следующие изменения могут иметь отношение к вашему заявлению:

  • автозавершение больше не происходит для всех шаблонов. Вместо этого он настроен только на файлы, заканчивающиеся на .html, .htm, .xml и .xhtml. Если у вас есть шаблоны с разными расширениями, вам следует переопределить метод select_jinja_autoescape().

  • В этом выпуске Flask больше не поддерживает приложения в формате zip. Эта функциональность может вернуться в будущих релизах, если на нее будет спрос. Удаление этой поддержки делает внутренний код Flask более понятным и устраняет пару небольших проблем, которые затрудняют отладку.

  • Функция create_jinja_loader исчезла. Если вы хотите настроить загрузчик Jinja сейчас, используйте вместо него метод create_jinja_environment().

Версия 0.4

Для разработчиков приложений нет никаких изменений, требующих внесения изменений в ваш код. Однако если вы разрабатываете расширение Flask, и это расширение имеет unittest-режим, вы можете захотеть связать активацию этого режима с новым флагом TESTING.

Версия 0.3

В версии Flask 0.3 появилась поддержка конфигурации и протоколирования, а также категории для мигающих сообщений. Все эти функции на 100% обратно совместимы, но вы, возможно, захотите ими воспользоваться.

Поддержка конфигурации

Поддержка конфигурации облегчает написание любого приложения, требующего определенной конфигурации. (Что, скорее всего, характерно для любого приложения).

Если раньше у вас был такой код:

app.debug = DEBUG
app.secret_key = SECRET_KEY

Вам больше не нужно этого делать, вместо этого вы можете просто загрузить конфигурацию в объект config. Как это работает, описано в Обработка конфигурации.

Интеграция протоколирования

Flask теперь настраивает для вас логгер с некоторыми базовыми и полезными настройками по умолчанию. Если вы используете свое приложение в производстве и хотите извлечь выгоду из автоматического протоколирования ошибок, вам может быть интересно подключить соответствующий обработчик журнала. Также вы можете начать записывать предупреждения и ошибки в логгер, когда это необходимо. Для получения дополнительной информации об этом читайте Ошибки приложения.

Категории для флэш-сообщений

К сообщениям Flash теперь можно добавлять категории. Это позволяет, например, по-разному отображать ошибки, предупреждения или обычные сообщения. Эта функция является опциональной, поскольку требует некоторого переосмысления кода.

Читайте об этом в шаблоне Мигание сообщения.