Есть ли побочные эффекты при добавлении метода в деклеративный класс в sqlalchemy? - PullRequest
0 голосов
/ 03 ноября 2018

Я задавал этот вопрос Как создать экземпляр записи таблицы, но не был добавлен в пониорм? где я спрашивал, как создать экземпляр класса, определенного как представление таблицы пониорм, без немедленного добавления Это. Используя sqlalchemy, где требуется явный add в экземпляре session, я думаю, что мне удалось использовать следующий код.

Сначала я создаю класс с именем AddInstance, в котором есть метод add, а затем наследую от него во всех определениях моей таблицы. Кажется, это работает (т.е. я могу создать экземпляр класса и добавить его, только если я хочу относительно легко), но я не уверен, есть ли какие-либо непреднамеренные побочные эффекты, или это очень далеко от передовой практики.

from sqlalchemy import create_engine                                               
from sqlalchemy.ext.declarative import declarative_base                         
from sqlalchemy.orm import sessionmaker, relationship                           
from sqlalchemy import Column, String, Integer                                  


engine = create_engine('sqlite:///:memory:')                                    
Base = declarative_base()                                                       
Session = sessionmaker(bind=engine)                                                


class AddInstance:                                                                 

    def add(self):                                                              
        session = Session()                                                        
        session.add(self)                                                       
        session.commit()


class Pizza(Base, AddInstance):                                                    
    __tablename__ = 'pizzas'                                                       
    id = Column(Integer, primary_key=True)                                         
    name = Column(String(50))                                                      
    toppings = relationship('Topping', back_populates='name')                      


class Topping(Base, AddInstance):                                                  
    __tablename__ = 'fruits'                                                       
    id = Column(Integer, primary_key=True)                                         
    name = Column(String(50))                                                      
    pizzas = relationship('Pizza', back_populates='name')                          


Base.metadata.create_all(engine)                                                   

1 Ответ

0 голосов
/ 03 ноября 2018

Побочных эффектов не будет, SQLAlchemy явно поддерживает добавление методов. Не имеет значения, определены ли эти методы в классе mixin или непосредственно в классе, производном от Base.

Цитирование из SQLAlchemy Учебник по реляционным объектам раздел документации :

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

( жирный акцент мины ).

Существует множество примеров кодовых баз, которые делают то же самое. Flask-SQLAlchemy предоставляет базовый класс Model для добавления атрибута query (устанавливается при создании декларативной базы ), что позволяет вам Topping.query(...) напрямую из модели класс, например.

Ваш метод add() имеет недостаток: он создает новый экземпляр Session() просто для добавления и фиксации вашего объекта. Это исключает его из обычной семантики управления состоянием сеанса , и если вы хотите сделать что-нибудь еще со своим вновь созданным объектом, вам нужно будет объединить его в существующий сеанс .

Обычная, лучшая практика для кода, включающего объекты SQLAlchemy, - это создание сеанса для управления транзакцией , набором операций, которые вместе должны завершаться успешно или неуспешно. Это включает в себя создание объектов; во многих реальных приложениях вы бы хотели избежать создания дополнительных строк в базе данных, когда другие операции, основанные на этих строках, не выполняются. Ваш метод .add() безоговорочно фиксирует каждый объект в отдельной транзакции. Вы можете вернуться к этому шаблону.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...