Ми вже говорили, що у SQLAlchemy є дуже багато вбудованих типів даних, які відповідають типам даних в SQL. Ці типи визначають, як саме твої дані будуть зберігатися в базі даних. Наприклад, рядки, цілі числа, дати і часи, булеві значення і навіть складні об'єкти, такі як JSON.
Основні типи даних
Давай розглянемо таблицю з основними типами даних і одразу спробуємо застосувати деякі з них на практиці.
| Тип SQLAlchemy | Опис |
|---|---|
String(size) |
Рядкове поле, де size задає максимальну довжину |
Text |
Необмежене текстове поле |
Integer |
Ціле число |
Float |
Число з плаваючою комою |
Boolean |
Булеве значення True/False |
Date |
Дата (без часу) |
DateTime |
Дата й час |
JSON |
Поле для зберігання JSON-об'єктів |
LargeBinary |
Для зберігання двійкових даних (наприклад, зображень) |
Enum |
Поле для перелічень (enums), наприклад, "Активний/Неактивний" |
А ось приклад використання. Можеш спробувати розширити його або створити свій власний.
from sqlalchemy import Column, Integer, String, Date, Boolean
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String(50)) # Максимальна довжина 50 символів
email = Column(String(120), unique=True, nullable=False) # Унікальний і обов'язковий
birth_date = Column(Date) # Поле для дати народження
is_active = Column(Boolean, default=True) # Прапорець активності користувача
Ось так просто — ми описали модель User з основними типами даних. Тепер давай розберемо деталі, додамо трохи магії і подивимось, як працювати з обмеженнями й валідацією.
Приклад розширеного визначення моделі
Дозволь показати трохи складніший приклад. У реальному житті тобі може знадобитись працювати з великою кількістю типів даних і додавати особливу логіку, наприклад, індекси й обмеження.
Складна модель:
from sqlalchemy import Column, Integer, Float, DateTime, String, ForeignKey, Boolean
from sqlalchemy.orm import relationship
import datetime
class Product(Base):
__tablename__ = "product"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False) # Назва продукту
price = Column(Float, nullable=False) # Ціна продукту
created_at = Column(DateTime, default=datetime.datetime.utcnow) # Час створення
is_available = Column(Boolean, default=True) # Прапорець наявності товару
# Зв'язок з таблицею категорій
category_id = Column(Integer, ForeignKey('category.id'))
category = relationship("Category", back_populates="products")
class Category(Base):
__tablename__ = "category"
id = Column(Integer, primary_key=True)
name = Column(String(50), unique=True, nullable=False) # Назва категорії
products = relationship("Product", back_populates="category") # Зв'язок з продуктами
Тут ми використовуємо:
- Зовнішній ключ
ForeignKeyдля зв'язку продуктів з категоріями. - Відношення через
relationship, щоб створити асоціацію між двома таблицями. - Поля з обмеженнями, такими як унікальність (
unique=True) і обов'язковість (nullable=False).
Валідація та обмеження
Іноді нам потрібно більше, ніж просто поля. Наприклад, інколи треба обмежити унікальність у базі даних або задати діапазон значень. SQLAlchemy дозволяє це робити "на льоту".
Унікальність:
email = Column(String(120), unique=True)
Тепер ніхто не зможе зареєструвати два акаунти з одним email-адресою.
Обмеження довжини:
username = Column(String(20), nullable=False)
Тут ми обмежили довжину імені користувача до 20 символів і зробили поле обов'язковим.
Щоб пришвидшити запити, можна додати індекси:
surname = Column(String(50), index=True)
Значення за замовчуванням:
created_at = Column(DateTime, default=datetime.datetime.utcnow)
а тепер давай використаємо все разом:
from sqlalchemy import Column, Integer, String, Float, DateTime, CheckConstraint
class Order(Base):
__tablename__ = 'order'
id = Column(Integer, primary_key=True)
product_id = Column(Integer, nullable=False)
quantity = Column(Integer, CheckConstraint('quantity > 0'), nullable=False) # Кількість має бути > 0
total_price = Column(Float, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.utcnow)
Користувацькі типи даних
Іноді треба створити свій власний тип даних. Наприклад, хочеш додати тип для зберігання "кольору" у форматі HEX.
Реалізація користувацького типу:
from sqlalchemy.types import TypeDecorator, String
class ColorType(TypeDecorator):
impl = String
def process_bind_param(self, value, dialect):
if not value.startswith("#"):
raise ValueError("Колір має бути у форматі HEX і починатися з #.")
return value
def process_result_value(self, value, dialect):
return value.upper() # Завжди повертати колір у верхньому регістрі
Використання в моделі:
class Theme(Base):
__tablename__ = 'theme'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
primary_color = Column(ColorType, nullable=False) # Поле для кольору
Таким чином, ти можеш додавати будь-яку поведінку до своїх типів даних.
Важливо знати: типові помилки
У процесі роботи зі схемами і типами даних можна нарватися на неприємності. Наприклад:
- Помилка узгодження типів: якщо ти намагаєшся використати рядок у полі, що очікує Integer, отримаєш виключення. Завжди перевіряй відповідність типів у своїй моделі й даних.
- Унікальні обмеження: додаючи
unique=True, врахуй, що в базі даних теж має бути індекс для цього. SQLAlchemy робить це автоматично, але якщо ти забув, індексація буде повільною. - Обмеження NOT NULL: якщо поле позначене як
nullable=False, а ти не передаси значення, запит завершиться помилкою.
SQLAlchemy — це потужний інструмент, який допомагає не лише працювати з даними, але й задавати строгі обмеження, покращувати продуктивність і навіть навчати розробників писати більш чіткі й продумані моделі даних. На наступному занятті ми будемо використовувати ці моделі для виконання CRUD операцій.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ