Декларирование Models

Вообще Flask-SQLAlchemy ведет себя как правильно сконфигурированная описательная база из расширения declarative. Мы рекомендуем прочитать документацию SQLAlchemy для полного восприятия. Однако, наиболее распространенные примеры отражены здесь.

Что нужно иметь ввиду:

  • Базовый класс для всех ваших моделей называется db.Model. Он хранится в экземпляре SQLAlchemy который вы создаете. Смотрите Быстрый старт для дополнительной информации.
  • Некоторые части требуемые в SQLAlchemy не являются обязательными в Flask-SQLAlchemy. Например имя таблицы устанавливается автоматически, если оно не было заданно. Оно образуется из названия класса с преобразованием имени в нижний регистр, так “CamelCase” преобразуется в “camel_case”. Чтобы определить имя таблицы, установите атрибут __tablename__.

Простой пример

Очень простой пример:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username

Использыйте Column для определения столбца. Имя столбца - это имя атрибута которому оно присвоенно. Если вы хотите использовать другое имя в таблице, вы можете указать необязательный первый аргумент, который является строкой определяющей имя столбца. Первичные ключи отмечаются с помощью primary_key=True. Несколько ключей могут быть отмечены как первичные ключи в этом случае они образуют составной первичный ключ.

Тип столбца является первый аргумент в Column. Вы можете указать их непосредственно или вызвать их в дальнейшем с дополнительным определением (например указать длинну). Следующие типы наиболее распространены:

Integer Числовой
String (size) Числовой с указанием размера
Text Более длинный текс в юникоде
DateTime Дата и время выраженные как объект Python datetime
Float Число с плавающей точкой
Boolean Логическое значение
PickleType Хранит pickled Python объект
LargeBinary Хранит большие произвольные бинарные данные

Связь Один-ко-Многим

Связь Один-ко-Многим являются наиболее распространенными. Поскольку связи объявляются, прежде чем они установлены вы можете использовать строки для обозначения классов, которые еще не созданы (например, если Person определяет свзяь к Address, которая объявляется позднее в файле).

Связи записываются с помощью функции relationship(). Однако внешний ключ должен быть объевлен отдельно с помощью класса sqlalchemy.schema.ForeignKey:

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address', backref='person',
                                lazy='dynamic')

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(50))
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))

Что же делает db.relationship()? Эта функция возвращает новое свойство, которое может сделать несколько вещей. В данном случае мы сказали ей указывать на класс Address и загружать их несколько. Откуда он знает, что будет возвращать более одного адреса? Потому что SQLAlchemy угадывает полезные преднастройки из вашего описания. Если вы хотели бы иметь свзяь один к одному можно указать uselist=False в relationship().

Итак что же изначают параметры backref и lazy? backref простой способ объявить новое свойство для класса Address. Вы можете также использовать my_address.person чтобы обратиться к человеку из этого адреса. lazy определяет, когда SQLAlchemy будет загружать данные из базы данных:

  • 'select' (значение по умолчанию) означет что SQLAlchemy будет загружать данные по мере необходимости в один заход с использованием стандартного оператора выбора.
  • 'joined' говорит SQLAlchemy загружать связи в том же запросе что и родительский используя оператор JOIN.
  • 'subquery' работает как 'joined', но SQLAlchemy использует подзапрос.
  • 'dynamic' является особено полезным, если у вас есть много элементов. Вместо того чтобы загружать элементы SQLAlchemy будет возвращать объект запроса, который вы можете дополнительно уточнить перед загрузкой элементов. Как правило, это как раз то, в чем вы нуждаетесь, если ожидаете более чем несколько элементов для этих связей.

Как вам определить lazy статус для backrefs? Используйте функцию backref()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address',
        backref=db.backref('person', lazy='joined'), lazy='dynamic')

Связь Многие-ко-Многим

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

tags = db.Table('tags',
    db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)

class Page(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship('Tag', secondary=tags,
        backref=db.backref('pages', lazy='dynamic'))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)

Здесь мы задали Page.tags как список тэгов загружаемых в один заход, потому что мы не ожидаем большого количества тегов на одной странице. Список страниц на тэг (Tag.pages) однако является динамическим backref. Как уже упоминалось выше, это означает, что вы получите объект запроса обратно и можете использовать для выборки в нем (прим.пер. слабо понял последнюю фразу =().

Оригинал этой страницы