Flask

Flask – компактный фреймворк для быстрой разработки веб-приложений. Он предоставляет минимальную необходимую функциональность и не навязывает никаких строгих правил в отношении структуры и архитектуры приложения (как это делает Django).

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

Основные преимущества Flask:

  • Минималистичность. Flask отличается небольшим размером – в нем есть все самое необходимое и нет ничего лишнего.
  • Гибкость. Фреймворк не диктует определенных правил и позволяет разработчику сохранить полный контроль над структурой приложения.
  • Простота в использовании. Он имеет несколько встроенных функций, которые позволяют сразу начать создавать полноценные веб-приложения, даже если у вас нет опыта в веб-разработке на Python. Например, у Flask есть встроенный сервер, поддержка сессий, обработчик форм, шаблонизатор.
  • Интеграция с дополнительными библиотеками. Фреймворк очень просто интегрируется с многочисленными библиотеками, которые расширяют его функциональность. Это позволяет создать гибкий, масштабируемый проект для любой сферы.
  • Простота тестирования. У Flask есть встроенный тестовый клиент, который максимально упрощает тестирование и отладку.

Установка

Flask лучше всего устанавливать в виртуальное окружение – это позволяет избежать появления ошибок, связанных с конфликтами версий различных библиотек и модулей. Выполните в cmd:python -m venv fproject\venv

Перейдите в только что созданную директорию:cd fproject

Активируйте окружение:venv\scripts\activate

И установите Flask:pip install flask

Активировать виртуальное окружение нужно перед каждым сеансом работы с Flask.

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»

Интересно, перейти к каналу

Простейшее приложение на Flask

Напишем приложение, которое будет выводить традиционное приветствие Hello, World! в браузере. Сохраните этот код в файле app.py в директории fproject:from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello, World!' if __name__ == '__main__': app.run()

Этот код создает объект приложения Flask с помощью класса Flask и присваивает его переменной app. Декоратор @app.route('/') устанавливает маршрут для главной страницы нашего приложения, а метод def hello()определяет, что будет отображаться на этой странице.

if __name__ == '__main__': проверяет, запускается ли данный файл как самостоятельное приложение, или импортируется как модуль. В нашем случае он запускается как независимое приложение, поэтому вызывается метод app.run(), который запускает веб-сервер Flask.

Запустите приложение в командой строке:(venv) C:\Users\User\fproject>app.py

Откройте адрес http://localhost:5000/ в браузере:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Flask по умолчанию использует порт 5000. При желании его можно изменить на более привычный 8000:app.run(port=8000)

Кроме того, можно включить режим отладки – тогда все возникающие ошибки будут отображаться на странице браузера, а при внесении любых изменений в файлы проекта сервер будет автоматически перезагружаться:app.run(debug=True)

Для остановки сервера нажмите Ctrl+C.

Маршруты в Flask

Маршруты – это URL-адреса, по которым пользователи могут открывать определенные страницы (разделы) веб-приложения. Маршруты в Flask определяются с помощью декоратора @app.route(). Для каждого маршрута можно написать отдельную функцию представления, которая будет выполнять какие-то действия при переходе по определенному адресу. Рассмотрим пример:from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Это главная страница.' @app.route('/about') def about(): return 'Здесь будет информация об авторе сайта.' @app.route('/blog') def blog(): return 'Это блог с заметками о работе и увлечениях.' if __name__ == '__main__': app.run()

Сохраните код, запустите приложение, последовательно откройте адреса:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Переменные в маршрутах

В URL можно передавать различные значения. Запустите этот код и перейдите по адресу, например, http://localhost:5000/user/EvilAdminfrom flask import Flask app = Flask(__name__) @app.route('/user/<username>') def user_profile(username): return f"Это профиль пользователя {username}" if __name__ == '__main__': app.run()

Имя пользователя, переданное в качестве переменной, будет показано на странице:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

А так можно передать в маршруте целое число:from flask import Flask app = Flask(__name__) @app.route('/user/<int:user_id>') def user_profile(user_id): return f"Это профиль пользователя с ID {user_id}" if __name__ == '__main__': app.run()

Перейдите по адресу, например, http://localhost:5000/user/5:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

GET- и POST-запросы

GET и POST – это HTTP-запросы, которые используются для отправки данных между клиентом и сервером.

GET-запрос применяют для получения данных от сервера. При выполнении GET-запроса клиент отправляет запрос на сервер, а сервер возвращает запрошенную информацию в ответ. GET-запросы могут содержать параметры в URL-адресе, которые используются для передачи дополнительных данных.

POST-запрос используют для отправки данных на сервер. При выполнении POST-запроса клиент отправляет данные на сервер, а сервер их обрабатывает. POST-запросы обычно применяют для отправки форм, с данными из которых нужно что-то сделать на бэкенде.

Рассмотрим простейший пример обработки формы авторизации. Базы данных для хранения учетных записей у нас пока нет, поэтому в приведенном ниже коде мы пропустим всю функциональность для проверки корректности логина и пароля (мы рассмотрим этот вопрос позже, в одном из заданий):from flask import Flask, request, render_template app = Flask(__name__) @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] # проверка логина и пароля return 'Вы вошли в систему!' else: return render_template('login.html') if __name__ == '__main__': app.run()

Маршрут @app.route('/login', methods=['GET', 'POST']) обрабатывает и POST, и GET-запросы: в первом случае он отправит данные на сервер, во втором – просто выведет страницу с формой авторизации.

Для вывода формы на странице сделаем простейший шаблон. Этот код нужно сохранить в файле login.html, в директории templates (в этой папке Flask по умолчанию ищет шаблоны):{% extends 'base.html' %} {% block content %} <div class="container"> <div class="row justify-content-center mt-5"> <div class="col-md-6"> <div class="card"> <div class="card-header"> <h1 class="text-center">Вход на сайт</h1> </div> <div class="card-body"> {% with messages = get_flashed_messages() %} {% if messages %} <div class="alert alert-danger"> <ul> {% for message in messages %} <li>{{ message }}</li> {% endfor %} </ul> </div> {% endif %} {% endwith %} <form method="post"> <div class="mb-3"> <label for="username" class="form-label">Логин:</label> <input type="text" class="form-control" id="username" name="username" required> </div> <div class="mb-3"> <label for="password" class="form-label">Пароль:</label> <input type="password" class="form-control" id="password" name="password" required> </div> <div class="text-center"> <button type="submit" class="btn btn-primary">Войти</button> </div> </form> </div> </div> </div> </div> </div> {% endblock %}

Никакие CSS стили к шаблону не подключены, поэтому он выглядит не слишком привлекательно. Но шаблон работает, а форма получает логин и пароль:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Шаблонизатор Jinja2

Шаблоны в Flask используются для динамического формирования веб-страниц. Шаблоны представляют собой HTML страницы, в которые можно передавать любые данные с бэкенда. К шаблонам можно подключать любые CSS-фреймворки типа Bootstrap и Tailwind, и любые JS-скрипты.

Поведением шаблонов управляет шаблонизатор Jinja2 – он предоставляет функциональность для создания условий, циклов, макросов, наследования и блоков. Главные преимущества шаблонизатора:

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

Наследование работает так:

  • Базовый шаблон, который обычно называется base.html, содержит общую разметку для сайта.
  • В base.html подключаются локальные и CDN-фреймворки (CSS, JS), задаются фоновые изображения и фавикон.
  • Дочерние шаблоны наследуют этот базовый шаблон и дополняют его своим собственным контентом.

Продемонстрируем наследование на примере. Сохраните в папке templates два файла. Это содержимое файла base.html – в нем подключается CSS-фреймворк Bootstrap, кастомные стили custom.css из статической папки static, иконки Font Awesome:<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>{% block title %}{% endblock %}</title> <!-- Bootstrap стили --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- иконки fontawesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <!-- кастомные стили --> <link rel="stylesheet" href="{{ url_for('static', filename='custom.css') }}"> </head> <body> <!-- навигация --> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container"> <a class="navbar-brand" href="#">Мой личный сайт</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse justify-content-end" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="#">Главная</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Обо мне</a> </li> </ul> </div> </div> </nav> <!-- контент дочерних шаблонов --> <div class="container my-3"> {% block content %} {% endblock %} </div> </body> </html>

Шаблон base.html также содержит верхнее меню для навигации по сайту – это меню будут наследовать все дочерние шаблоны. Вот пример дочернего шаблона about.html:{% extends 'base.html' %} {% block title %}Мое резюме{% endblock %} {% block content %} <div class="container my-5"> <h1 class="text-center mb-4">Мое резюме</h1> <div class="row"> <div class="col-md-6"> <h2>Образование</h2> <h4>Московский политехнический институт</h4> <p class="mb-0">Бакалавр Computer Science</p> <p class="text-muted">2016 - 2020</p> </div> <div class="col-md-6"> <h2>Опыт работы</h2> <h4>Web Developer - XYZ компания</h4> <p class="mb-0">2019 - н.в.</p> <p class="text-muted">- Разработка и поддержка веб-приложений</p> <p class="text-muted">- Работа с Python, Django, HTML/CSS, JavaScript, MySQL</p> </div> </div> <div class="row mt-5"> <div class="col-md-6"> <h2>Навыки</h2> <ul class="list-group"> <li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> Python</li> <li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> Django</li> <li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> HTML/CSS</li> <li class="list-group-item border-0 py-1"><i class="fa fa-cog"></i> JavaScript</li> </ul> </div> <div class="col-md-6"> <h2>Проекты</h2> <h4>Сайт для продажи автомобилей</h4> <p class="text-muted mb-0">- Разработка сайта с использованием Django</p> <p class="text-muted">- Интеграция с API маркетплейса для получения данных об автомобилях</p> <h4>Игровой блог</h4> <p class="text-muted mb-0">- Разработка блога с использованием Django</p> <p class="text-muted">- Возможность создавать учeтные записи пользователей и писать комментарии</p> </div> </div> <div class="row mt-5"> <div class="col-md-6"> <h2>Контакты</h2> <p class="mb-0"><i class="fa fa-phone"></i> Телефон: +990123456789</p> <p class="mb-0"><i class="fa fa-envelope"></i> Email: example@example.com</p> <p class="mb-0"><i class="fa fa-github"> GitHub: <a href="https://github.com/example"></i>example</a></p> </div> <div class="col-md-6"> <h2>Языки</h2> <ul class="list-group"> <li class="list-group-item border-0 py-1"><i class="fa fa-check-circle"></i> Английский (C1)</li> <li class="list-group-item border-0 py-1"><i class="fa fa-check-circle"></i> Немецкий (B2)</li> <li class="list-group-item border-0 py-1"><i class="fa fa-check-circle"></i> Русский (родной)</li> </ul> </div> </div> </div> {% endblock %}

Фон страницы шаблонизатор берет из файла static/customs.css:body { background-color: #e5e5e5; }

А код для вывода страницы выглядит так:from flask import Flask, render_template app = Flask(__name__) @app.route('/about') def about(): return render_template('about.html') if __name__ == '__main__': app.run(debug=True)

Запустите приложение, откройте адрес http://localhost:5000/about:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Работа с базой данных

Для работы с базами данных в Flask удобно использовать ORM SQLAlchemy. Как уже упоминалось в предыдущей главе о SQLite, ORM играет роль своеобразной прослойки между приложением и СУБД SQLite, и позволяет работать с базами без использования языка SQL. Надо заметить, что работать с базами данных в SQLAlchemy немного сложнее, чем в Django ORM, но гораздо проще, чем в чистом Python.

Начнем с установки SQLAlchemy в виртуальное окружение:pip install flask-sqlalchemy

В SQLAlchemy основой для создания таблиц в базе данных служат модели (специальные классы). Поля классов определяют структуру таблицы, которая будет использоваться для хранения информации в базе данных. В полях классов можно задавать типы данных, которые соответствуют типам данных в БД, например, String для хранения строк, Integer для целых чисел, Float для плавающих чисел и т.д.

SQLAlchemy, как и другие ORM, очень упрощает создание связей между таблицами. В приведенном ниже примере используется связь один ко многим (ForeignKey), поскольку у одного исполнителя может быть несколько альбомов, а в одном альбоме всегда будет несколько треков:from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class Artist(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) class Album(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100), nullable=False) year = db.Column(db.String(4), nullable=False) artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'), nullable=False) artist = db.relationship('Artist', backref=db.backref('albums', lazy=True)) class Song(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100), nullable=False) length = db.Column(db.String(4), nullable=False) track_number = db.Column(db.Integer, nullable=False) album_id = db.Column(db.Integer, db.ForeignKey('album.id'), nullable=False) album = db.relationship('Album', backref=db.backref('songs', lazy=True))

Сохраните этот код в файле models.py – мы будем импортировать модели из него в главный файл приложения app.py и в скрипт create_db.py, который создает базу данных и заполняет ее тестовой информацией.

Код для create_db.py будет следующим:from flask import Flask from models import Artist, Album, Song, db app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///music.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) if __name__ == '__main__': with app.app_context(): db.create_all() # создаем тестовых исполнителей artist1 = Artist(name='The Rolling Stones') artist2 = Artist(name='Jefferson Airplane') artist3 = Artist(name='Nine Inch Nails') artist4 = Artist(name='Tool') db.session.add_all([artist1, artist2, artist3, artist4]) db.session.commit() # создаем тестовые альбомы album1 = Album(title='Aftermath', year='1966', artist=artist1) album2 = Album(title='Beggars Banquet', year='1968', artist=artist1) album3 = Album(title='Surrealistic Pillow', year='1967', artist=artist2) album4 = Album(title='Broken', year='1992', artist=artist3) album5 = Album(title='The Fragile', year='1999', artist=artist3) album6 = Album(title='Lateralus', year='2001', artist=artist4) album7 = Album(title='AEnima', year='1996', artist=artist4) album8 = Album(title='10,000 Days', year='2006', artist=artist4) # создаем тестовые песни song1 = Song(title='Paint it Black', length='4:20', track_number=1, album=album1) song2 = Song(title='Sympathy For The Devil', length='3:53', track_number=2, album=album1) song3 = Song(title='White Rabbit', length='3:42', track_number=5, album=album3) song4 = Song(title='Wish', length='3:46', track_number=6, album=album4) song5 = Song(title='Starfuckers, Inc.', length='5:00', track_number=1, album=album5) song6 = Song(title='Schism', length='6:46', track_number=7, album=album6) song7 = Song(title='Eulogy', length='8:29', track_number=3, album=album7) song8 = Song(title='Vicarious', length='7:07', track_number=5, album=album8) db.session.add_all([album1, album2, album3, album4, album5, album6, album7, album8, song1, song2, song3, song4, song5, song6, song7, song8]) db.session.commit()

Этот код наглядно демонстрирует, как именно создаются записи, и какие между ними существуют связи. Чтобы создать и заполнить базу, запустите файл в активированном виртуальном окружении:(venv) C:\Users\User\fproject>create_db.py

В реальных приложениях базу данных удобнее заполнять, например, с помощью модуля csv – мы рассмотрим этот метод ниже, в одном из заданий.

Главный файл приложения app.py выглядит так:from flask import Flask, render_template from models import Artist, Album, Song, db app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///music.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # связываем приложение и экземпляр SQLAlchemy db.init_app(app) @app.route('/songs') def songs(): songs_list = Song.query.all() return render_template('songs.html', songs=songs_list) if __name__ == '__main__': app.run(debug=True)

Шаблон songs.html использует тот же самый базовый base.html, что и предыдущий пример:{% extends 'base.html' %} {% block title %} Мои любимые песни {% endblock %} {% block content %} <h1 class="mb-5">Мои любимые песни</h1> <div class="card-columns"> <div class="row"> {% for song in songs %} <div class="col-md-3"> <div class="card mb-3"> <div class="card-header fw-bold">{{ song.title }}</div> <div class="card-body"> <p class="badge bg-primary text-wrap">{{ song.album.artist.name }}</p> <p class="card-text">Альбом: <strong>{{ song.album.title }}</strong></p> <p class="card-text">Длина: {{ song.length }} минут</p> <p class="card-text">Номер трека: {{ song.track_number }}</p> <p class="card-text">Дата релиза: {{ song.album.year }}</p> </div> </div> </div> {% endfor %} </div> </div> {% endblock %}

После создания шаблона можно запустить приложение:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Практика

Задание 1

Напишите Flask-приложение, которое выводит в шаблон index.html приветствие для пользователя. Приветствие зависит от времени суток:

  • С 6:00 до 12:00 – «Доброе утро»
  • С 12:00 до 18:00 – «Добрый день»
  • С 18:00 до 24:00 – «Добрый вечер»
  • С 00:00 до 6:00 – «Доброй ночи»

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Код для app.py выглядит так:from flask import Flask, render_template import datetime app = Flask(__name__) @app.route('/') def index(): now = datetime.datetime.now() if now.hour >= 6 and now.hour < 12: greeting = 'Доброе утро' elif now.hour >= 12 and now.hour < 18: greeting = 'Добрый день' elif now.hour >= 18 and now.hour < 24: greeting = 'Добрый вечер' else: greeting = 'Доброй ночи' return render_template('index.html', greeting=greeting) if __name__ == '__main__': app.run(debug=True)

Для вывода приветствия используются шаблоны base.html и index.html.

Задание 2

Напишите Flask-приложение, которое с помощью шаблона выводит пронумерованный список дел.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Это код приложения app.py:from flask import Flask, render_template app = Flask(__name__) @app.route('/') def task_list(): tasks = ["Выгулять собаку", "Погладить рубашку", "Зайти в супермаркет", "Убрать на кухне", "Дописать статью", "Позвонить тимлиду"] return render_template('task_list.html', tasks=tasks) if __name__ == '__main__': app.run()

Нумерацию в Jinja2 легко реализовать с помощью loop.index:<!DOCTYPE html> <html> <head> <title>Мой список важных дел</title> <style> ul.no-bullets { list-style-type: none; } </style> </head> <body> <h1>Список дел на сегодня:</h1> <ul class="no-bullets"> {% for task in tasks %} <li>{{loop.index}}. {{ task }}</li> {% endfor %} </ul> </body> </html>

Задание 3

Напишите app.py и шаблон welcome.html, которые выводят различный контент для пользователей с разными правами доступа:

  • Админ имеет полный доступ.
  • Модератор может редактировать записи и комментарии.
  • Рядовой пользователь может создавать записи от своего имени и просматривать френдленту.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

В приложении app.py можно определить только маршрут, вся функциональность по определению уровней доступа находится в шаблоне:<!DOCTYPE html> <html> <head> <title>Личный кабинет</title> </head> <body> {% if user_level == 'admin' %} <h1>Привет, админ!</h1> <p>У тебя есть доступ ко всем настройкам.</p> <a href="#">Редактирование профилей</a> <a href="#">Создание учетных записей</a> <a href="#">Публикация статей</a> {% elif user_level == 'moderator' %} <h1>Привет, модератор!</h1> <p>У тебе есть доступ к редактированию записей.</p> <a href="#">Редактирование записей</a> <a href="#">Модерация комментариев</a> {% else %} <h1>Привет, пользователь!</h1> <p>У тебя нет доступа к редактированию контента и настроек.</p> <a href="#">Новая запись</a> <a href="#">Записи друзей</a> {% endif %} </body> </html>

Задание 4

Напишите скрипт для создания и заполнения базы данных SQLite данными о книгах из файла books.json, а также app.py и шаблоны, которые выводят:

  • Карточки с информацией о книгах.
  • Карточку отдельной книги.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Напишем модель Book и скрипт, который создает и заполняет базу из json-файла. Затем создадим app.py с двумя маршрутами – для вывода всех книг, и для вывода отдельной книги:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Задание 5

Для онлайн-магазина нужно написать модуль, который поможет сотрудникам сделать инвентаризацию. Приложение состоит из базы данных, в которой таблицы связаны сложными отношениями:

  • Каждый производитель (Manufacturer) поставляет несколько типов товаров (Category) – ноутбуки, наушники, смартфоны и так далее.
  • Одну и ту же категорию товаров могут производить несколько компаний.
  • В каждой категории может быть множество товаров (Item).

Нужно реализовать вывод всех товаров по поставщикам и по категориям. Все данные о товарах находятся в файле info.csv.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Файл models.py, описывающий структуру базы данных, выглядит так:from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() manufacturer_items = db.Table('manufacturer_items', db.Column('manufacturer_id', db.Integer, db.ForeignKey('manufacturer.id'), primary_key=True), db.Column('item_id', db.Integer, db.ForeignKey('item.id'), primary_key=True) ) class Manufacturer(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) items = db.relationship('Item', secondary=manufacturer_items, backref=db.backref('manufacturers', lazy=True)) def __repr__(self): return '<Manufacturer %r>' % self.name class Category(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) items = db.relationship('Item', backref='category') def __repr__(self): return '<Category %r>' % self.name class Item(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) description = db.Column(db.String(255), nullable=False) price = db.Column(db.Float, nullable=False) quantity = db.Column(db.Integer, nullable=False, default=0) category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False) def __repr__(self): return '<Item %r>' % self.

Для заполнения базы данными из файла info.csv напишем скрипт. Приложение использует 4 шаблона:

За вывод всех товаров определенного производителя в отдельной категории отвечает эта функция:@app.route('/<manufacturer>/<category>') def show_items(manufacturer, category): items = Item.query.join(Item.manufacturers).join(Item.category).\ filter(Manufacturer.name == manufacturer).\ filter(Category.name == category).all() return render_template('items.html', manufacturer=manufacturer, category=category, items=items)

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Задание 6

Для супермаркета нужно написать веб-приложение, которое выводит список товаров на складе и позволяет добавлять новые.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Приложение состоит из файлов app.pycreate_db.py и models.py. Для добавления новых товаров используется шаблон add.html и маршрут/функция add:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Задание 7

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

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Начнем с создания базы данных на основе моделей. Функции add_patient, edit_patient, delete_patient реализованы в приложении app.py. Шаблоны add.html и edit.html обеспечивают добавление и редактирование карточек:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Задание 8

Напишите модуль аутентификации для Flask-приложения. Необходимо реализовать:

  • регистрацию;
  • проверку учетных данных при входе;
  • перенаправление на страницу профиля.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Проект включает в себя файлы app.pycreate_db.py и models.py. Кроме того, модуль использует шаблоны:

После регистрации и входа пользователь перенаправляется на страницу своего профиля:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Задание 9

Напишите веб-приложение для хранения заметок. Необходимо реализовать набор CRUD операций – вывод, добавление, редактирование и удаление заметок. При создании базы данных следует учесть, что заметка может относиться только к одной категории, а в категории может быть множество заметок. На главной странице выводятся все заметки, причем текст ограничивается первыми 300 символами. Нажатие на ссылку «Далее» открывает страницу с полным текстом заметки.

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

База данных для приложения создается с помощью скрипта create_db.py на основе моделей. CRUD операции описаны в app.py. При нажатии на название категории шаблон и маршрут categoryвыводят все заметки, относящиеся к данной теме.

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Задание 10

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

Пример:

? Самоучитель по Python для начинающих. Часть 23: Основы веб-разработки на Flask

Решение:

Прежде всего разработаем модели TagCategory и Post, а затем создадим на их основе базу данных при помощи скрипта.

Приложение использует следующие шаблоны:

CRUD операции реализованы в главном файле приложения app.py. Чтобы самые свежие записи выводились первыми, в models.py мы определили метод newest_first. При нажатии на ссылку «Читать» выводится полный текст записи: