Сейчас мы отдаем текст страницы сайта просто как результат функции. Что конечно здорово, но если представить, что у нас будет даже просто болванка под страницу со всеми этими html/head/body и прочими штуками писать очень быстро станет не интересно.
Специально для таких целей во flask реализовал механизм шаблонов. Как же это работает? Давайте создадим папку templates

теперь добавим в эту папку файлик index.html
и загоним в него стандартную болванку текста с каким-нибудь текстом

если запустить сервер flask --app server --debug run
и открыть ссылку http://127.0.0.1:5000 то увидим все тот же текст что и в прошлой подсказке

как же нам показать именно наш файлик? Для этого надо заставить шаблон отрендерить этот файлик. Для этого пишем в нашей функции hello_world

обновим теперь страницу в браузере. И проверим что появится:

о, теперь другое дело! =)
Создаем дополнительные страницы
Теперь можно попробовать сделать несколько страниц. Создадим файлики about.html
и best_page.html

как же нам подключить их к серверу?
Для этого надо в файлике нашего сервера добавить две дополнительные функции под каждую страницу, вот так:

теперь если попробовать открывать ссылки http://127.0.0.1:5000/about и http://127.0.0.1:5000/best_page то откроется содержимое наших файлов. Собственно, то что мы и хотели.
Мы можем даже сделать подобие навигации. Добавив в каждый ссылки на другие страницы:

ну и все, красота, можно теперь переходить между страничками! =О

и тут вероятно возникает вопрос, а нафига мы все делали если все тоже самое можно реализовать без всяких python с его фласками, бери liveserver и пили?)
А вот сейчас и разберемся
Использование шаблонизатора Jinja2
Во flask интегрирован шаблонизатор jinja, который позволяет очень много всего делать с html страницами, а в частности собирать их из кусочков.
Давайте воспользуемся его возможностями!)
Выносим навигацию в подшаблон
Вот у нас сейчас навигация на всех страницах одинаковая. Давайте вынесем ее в отдельный файлик и подключим этот файлик. Я создам подпапку components
в папке templates
и добавлю в нее файлик _navigation.html

а в файлике index.html пишем так

то же самое делаем с остальными файлами, получится так

теперь если попробовать пооткрывать ссылки все будет работать также

но вы только гляньте сколько строк мы сэкономили! =)
Создаем болванку страницы
Далее глянем на наши страницы еще раз и увидим, что выглядят они не особо по разному.
В принципе можно было вынести, например, head в отдельный файл и тоже подключать его через include. Мы б так сэкономили бы еще кучу места.
Но у jinja есть кое-что получше.
Так называемый механизм наследования шаблонов.
Работает он следующим образом. Вы создаете новый html файлик и описываете шаблон, а в тех местах где должен быть уникальный контент вставляете специальную конструкцию block
Пробуем. Создаем файлик __layout.html
(у меня два нижних подчеркивания, будьте внимательны!), который выглядит как все остальные файлы, только на месте где у страниц потенциально может находится разный контент мы вставляем
{% block content %}{% endblock %}
вот так получается

Наследуем базовый шаблон
а теперь возьмем все наши файлики страниц и наследуем их от этого базового файла. А уникальный контент пропишем в block. Выглядит это так:

то есть теперь у наших файликов страниц в начале есть строчка
{% extends "__layout.html" %}
которая говорит, что данная страница будет иметь такую же размтеку как и __layout.html
.
А вторая конструкция
{% block content %}
тут у всех страниц свой текст
{% endblock %}
указывает что надо подставить на место {% block content %}{% endblock %}
исходного шаблон __layout.html
, таким образом мы получаем новый шаблон с уникальным содержимым! =)
Опять же если теперь проверить как оно работает, то работает все так же как и раньше

только больше не надо заниматься прописыванием повторяющихся частей.
Подключение бутстрапа
Мы можем даже подключить bootstrap в __layout.html
. Просто добавив соответствующие стили и скрипты:

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

а вот ее исходный код

Сборку файлика из частей собственно и осуществляет компилятор jinja шаблонов.
Но вы только прикиньте насколько меньше надо писать кода! : )
Такие дела =)