Проблема наследования в SQLAlchemy - PullRequest
1 голос
/ 15 марта 2012

Мне нужна помощь в понимании того, как наследование работает в SQLAlchemy. Я создал базовый класс для пользователя с некоторыми базовыми функциями. А затем некоторые конкретные пользователи (администратор, cooluser, uncooluser). Каждый из них обладает уникальной функциональностью, поэтому я решил использовать наследование в SQLAlchemy. Проблема в том, что мне нужно иметь возможность обновить пользователя до cooluser или uncooluser и понизить версию cooluser до пользователя в любое время.

class User(Base):
    __tablename__ = 'tbl_users'
    __table_args__ = {'mysql_engine': 'InnoDB'}

    user_id = Column(Integer, primary_key = True, unique = True, nullable = False)
    user_name = Column(String(100), nullable = False, unique = True)
    password = Column(String(100), nullable = False)
    user_type = Column('user_type', String(50))
    first_name = Column(String(50), nullable = False)
    last_name = Column(String(50), nullable = False)
    address = Column(String(50), nullable = False)
    city = Column(String(20), nullable = False)
    postal_code = Column(String(10), nullable = False)
    country_id = Column(Integer, ForeignKey(Contries.country_id))

    country = relationship('Country', backref = 'users')

    query = Session.query_property()

    __mapper_args__ = {'polymorphic_on': user_type, 'polymorphic_identity': 'User'}
class CoolUser(User):
    __tablename__ = 'tbl_cool_user'
    __table_args__ = {'mysql_engine': 'InnoDB'}
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'}

    cool_user_id = Column(Integer, ForeignKey(User.user_id, ondelete = 'CASCADE'), primary_key = True)
    cool_user_balance = Column(Numeric(15, 3))

Могу ли я создать CoolUser, не создавая новую строку в 'tbl_users', но используя существующую? Можно изменить некоторые настройки, чтобы при удалении CoolUser он просто удалял запись в «tbl_cool_user», а не «tbl_user»?

Мне не хватает точки наследования в SQLAlchemy?

Ответы [ 3 ]

6 голосов
/ 15 марта 2012

Мне не хватает точки наследования в SQLAlchemy?

Я думаю, что вы неправильно используете концепцию inheritance вообще, и даже не в специфике реализации SA.
В классическом Animal (Cat, Dog (Terier)) типе иерархии вы когда-нибудь представляли, что Кошка будет повышена / понижена по отношению к Собаке, или даже к определенному типу Собаки? Я так не думаю. Кроме того, я могу себе представить, что некоторые CoolUser также могут быть Administrator в то же время. Как вы решите этот тип отношений?

Следовательно, для ваших требований наследование - это не та концепция, которую следует использовать для решения этой модели с изменением состояния. Я хотел бы предложить Google для User-Role тип отношений и реализации. Вам все равно придется решить проблему хранения данных, относящихся к ролям.


Как упоминалось @ aquavitae : в SA вы можете взломать и изменить user_type. Но учтите, что в этом случае произойдет следующее:

  • при загрузке объекта из базы данных его класс будет отражать новый тип (GOOD)
  • при понижении класса объекта (от CoolUser до User) строка, соответствующая CoolUser, будет не удалена (я думаю, что это ПЛОХО, но может быть и в порядке)
  • при обновлении объекта (от пользователя до CoolUser) новая строка для таблицы CoolUser не будет создана, и все ваши значения будут равны NULL. Таким образом, установка / добавление любого свойства, хранящегося в не созданной строке, приведет к приятной ошибке. И когда вы запрашиваете определенный подкласс, вы не получите объект обратно, так как INNER JOIN используется для извлечения объекта. (BAD)
  • Таким образом, не меняйте кошку на собаку
1 голос
/ 15 марта 2012

Не думаю, что вы должны использовать 'polymorphic_on' и 'polymorphic_identity' в одной и той же таблице.Что вам нужно сделать, это создать базовую таблицу User, содержащую всех пользователей (т.е. с mapper_args 'polymorphic_on'), затем CoolUser из этого подкласса (с 'polymorphic_identity'):

class User(Base):
    ...
    __mapper_args__ = {'polymorphic_on': user_type}

class CoolUser(User):
    ...
    __mapper_args__ = {'polymorphic_identity': 'CoolUser'}

Затем выможно изменить user_type, как вам нравится.

0 голосов
/ 15 марта 2012

Вы должны использовать Наследование бетонного стола .Все все общие атрибуты в базовой таблице и создают 2 разных CoolUser и UnCoolUser.

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