Flask-SQLAlchemy — Проектирование моделей базы данных
В этой главе вы узнаете, как определять модели данных с помощью Flask-SQLAlchemy, создавать таблицы базы данных SQLite и вставлять тестовые данные.
Зачем использовать ORM?
Написание SQL-инструкций напрямую для работы с базой данных утомительно и чревато ошибками.
ORM (объектно-реляционное отображение)Он позволяет определять структуры таблиц с помощью классов Python и манипулировать данными с помощью методов Python.
Flask-SQLAlchemy — это интеграция SQLAlchemy с Flask, которая оборачивает типовые операции и упрощает конфигурацию.
Установка и настройка
(venv) $ pip install flask-sqlalchemy
Пример
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# Путь к файлу базы данных SQLite (расположен в корневом каталоге проекта)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
# Отключить отслеживание изменений (экономит память; в будущих версиях будет отключено по умолчанию)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Создать экземпляр db и привязать его к app
db = SQLAlchemy(app)
sqlite:///blog.dbТри косые черты в нём указывают на относительный путь. База данных SQLite — это просто файл, для которого не требуется устанавливать программное обеспечение базы данных, что делает её идеальной для разработки и тестирования.
Определение моделей: Post и Category
Пример
from datetime import datetime
from app import db
class Category(db.Model):
"""Категория статьи"""
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(50), unique=True, nullable=False)
slug = db.Column(db.String(50), unique=True, nullable=False)
# backref: В объекте Category можно использовать .posts, чтобы получить все его статьи в обратном порядке.
posts = db.relationship('Post', backref='category', lazy='dynamic')
def __repr__(self):
return f'<Category {self.name}>'
class Post(db.Model):
"""Запись блога"""
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
slug = db.Column(db.String(200), unique=True, nullable=False)
summary = db.Column(db.Text, default='')
content = db.Column(db.Text, nullable=False)
# Внешний ключ: db.ForeignKey('table_name.field_name')
category_id = db.Column(db.Integer, db.ForeignKey('categories.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f'<Post {self.title}>'
Распространённые типы полей
| Тип поля | Тип в базе данных | Общие параметры |
|---|---|---|
| db.Integer | INTEGER | primary_key, autoincrement |
| db.String(N) | VARCHAR(N) | unique, nullable, default |
| db.Text | TEXT | default |
| db.DateTime | DATETIME | default, onupdate |
| db.Boolean | BOOLEAN | default |
| db.ForeignKey('table.field') | FOREIGN KEY | — |
Создание таблицы базы данных
В отличие от migrate в Django, Flask требует ручной инициализации таблиц базы данных.
(venv) $ flask shell # 进入 Flask 交互式 Shell
Пример
from app import db
db.create_all() # Создать таблицы базы данных для всех моделей
exit()
После выполнения в корневом каталоге проекта будет создано следующееblog.dbФайл.
db.create_all()Создаёт таблицу, только если она не существует. Если вы измените структуру модели (например, добавив новые поля), таблица не обновится автоматически. В продакшене следует использовать Flask-Migrate (глава 5) для управления изменениями структуры.
Используйте flask shell для вставки тестовых данных.
Пример
from app import db
from models import Category, Post
# 1. Создайте категорию
py_cat = Category(name='Python', slug='python')
css_cat = Category(name='CSS', slug='css')
flask_cat = Category(name='Flask', slug='flask')
db.session.add_all([py_cat, css_cat, flask_cat])
db.session.commit()
# 2. Создание статьи
post1 = Post(
title='Полное руководство по Flask для начинающих',
slug='flask-beginner-guide',
summary=Изучите Flask с нуля, охватывая основные концепции, такие как маршрутизация, шаблоны, ORM.,
content=<h2>Почему стоит изучать Flask?</h2><p>Flask — самый гибкий веб-микрофреймворк в Python...</p>,
category=flask_cat
)
post2 = Post(
title=Сопрограммы Python: объяснение,
slug='python-coroutine',
summary=Разберитесь с asyncio, корутинами и циклами событий в одной статье.,
content=<h2>Что такое корутина?</h2><p>Корутина — это более лёгкое решение для конкурентности, чем потоки...</p>,
category=py_cat
)
post3 = Post(
заголовок=Практическое руководство по CSS Grid Layout,
slug='css-grid-layout',
краткое описание=Легко реализуйте сложные адаптивные макеты с помощью CSS Grid.,
содержание=<h2>Начало работы с Grid</h2><p>Grid — это двумерная система компоновки...</p>,
category=css_cat
)
db.session.add_all([post1, post2, post3])
db.session.commit()
# 3. Проверка запросов
print(Post.query.all())
print(Post.query.filter(Post.category_id == 1).all())
Основные запросы Flask-SQLAlchemy
| Методы | Эквивалентный SQL | Возвращаемое значение |
|---|---|---|
| Post.query.all() | SELECT * FROM posts | Список |
| Post.query.get(1) | WHERE id = 1 | Один объект или None |
| Post.query.get_or_404(1) | WHERE id = 1 | Один объект или автоматически возвращает 404 |
| Post.query.filter_by(category_id=1).all() | WHERE category_id=1 | Список |
| Post.query.filter(Post.title.ilike('%flask%')).all() | WHERE title LIKE '%flask%' | Список |
| Post.query.order_by(Post.created_at.desc()).all() | ORDER BY created_at DESC | Список |
Итоги главы
В этой главе вы освоили полный рабочий процесс Flask-SQLAlchemy: установку и настройку SQLALCHEMY_DATABASE_URI, определение моделей с помощью db.Model (типы полей/внешние ключи/relationship), инициализацию таблиц с помощью db.create_all() и вставку и запрос данных в оболочке flask shell.
На данный момент структуры данных для постов и категорий уже созданы в базе данных SQLite.
Другие расширения