Найти - Пользователи
Полная версия: Вопрос по sqlalchemy.Column
Начало » Базы данных » Вопрос по sqlalchemy.Column
1
Stright
Всем здравствуйте!
Пишу сохранение истории изменения значений атрибутов модели алхимии. Перечень атрибутов, которые важны для истории, сохраняю в атрибуте класса history_attributes, при этом в целях удобства рефакторинга использую не строковые названия атрибутов, а сами дескрипторы.
 from sqlalchemy import Integer, Column, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class HistoryAttribute:
    def __init__(self, descriptor, display_name, use_message=False):
        self.name = descriptor.name
        self.display_name = display_name
        self.use_message = use_message
class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    first_name = Column(String(100))
    email = Column(String(100))
    history_attributes = (
        HistoryAttribute(descriptor=first_name, display_name='User name'),
        email
    )
print(User.history_attributes[0].name)
>>> None
print(User.history_attributes[1].name)
>>> email
Почему пропадает атрибут name экземпляра Column, если дескриптор передавать в качестве аргумента в конструктор другого класса? Конечно, можно написать first_name = Column('first_name', String(100)), но хочется единообразия, потому как нигде в приложении я не передаю явно name в конструктор Column.
Пока проблему обошел заменив в history_attributes HistoryAttribute на namedtuple, который уже потом и передаю в конструктор класса HistoryAttribute, но это как то сильно похоже на костыль
PooH
А у него в этот момент еще не установлено значение для name. Оно появляется после цепочки
DeclarativeMeta.__init__
_as_declarative
_MapperConfig.setup_mapping
_MapperConfig.__init__
_extract_declared_columns
_undefer_column_name - вот тут имя атрибута класса отдается в дескриптор.
А экземпляр HistoryAttribute инициализируется до вызова DeclarativeMeta.__init__. Можно вот так
  
class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    first_name = Column(String(100))
    email = Column(String(100))
 
User.history_attributes = (
        HistoryAttribute(descriptor=User.first_name, display_name='User name'),
        User.email
    )
или наследоваться от DeclarativeMeta, сделать в нем передачу в HistoryAttribute имен после того как их получили дескрипторы и передать declarative_base свой класс в параметре metaclass
Stright
Спасибо большое за помощь и подробный ответ! Примерно то же самое мне ответили на stackoverflow, оставил такой вариант:
 class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    first_name = Column(String(100))
    email = Column(String(100))
    @classmethod
     def get_history_attributes(cls):
        return (
            HistoryAttribute(descriptor=cls.first_name, display_name='User name'),
            cls.email
        )
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB