Как расширить `getter`-функциональность SQLAlchemy's association_proxy? - PullRequest
2 голосов
/ 30 января 2012

Редактировать: Я хотел бы смоделировать 1 to 0:1 отношение между User и Comment (у пользователя может быть ноль или один комментарий).Вместо доступа к объекту Comment я бы предпочел непосредственно получить доступ к самому комментарию.Использование SQLAlchemys association_proxy идеально подходит для этого сценария , за исключением , с одной стороны: доступ к User.comment до связывания Comment.Но в этом случае я предпочел бы ожидать None вместо AttributeError в качестве результата.

Посмотрите на следующий пример:

import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy import Column, Integer, Text, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy

Base = declarative_base()

class User(Base):
  __tablename__ = 'users'
  id = Column(Integer, primary_key=True)
  name = Column(Text)

  def __init__(self, name):
      self.name = name

  # proxy the 'comment' attribute from the 'comment_object' relationship
  comment = association_proxy('comment_object', 'comment')


class Comment(Base):
  __tablename__ = 'comments'
  id = Column(Integer, primary_key=True)
  comment = Column('comment', Text, nullable=False, default="")
  user_id = Column(ForeignKey('users.id'), nullable=False, unique=True)
  # user_id has to be unique to ensure that a User can not have more than one comments

  def __init__(self, comment):
      self.comment = comment

  user_object = orm.relationship(
      "User",
      uselist=False, # added after edditing the question
      backref=orm.backref('comment_object', uselist=False)
      )

if __name__ == "__main__":
  engine = sa.create_engine('sqlite:///:memory:', echo=True)
  Session = orm.sessionmaker(bind=engine)
  Base.metadata.create_all(engine)
  session = Session()

Теперь следующий код выдает AttributeError:

u = User(name="Max Mueller")
print u.comment

Как лучше всего перехватить это исключение и указать вместо него значение по умолчанию (например, пустую строку)?

Ответы [ 2 ]

3 голосов
/ 02 февраля 2012

На самом деле не нужно association_proxy для этого. Вы могли бы действительно хорошо справиться с обычной property. AttributeError (вероятно) вызвано тем, что комментарий_объект сам по себе None, поскольку нет зависимой строки, а None не имеет comment атрибута.

class User(Base):
  __tablename__ = 'users'
  id = Column(Integer, primary_key=True)
  name = Column(Text)

  def __init__(self, name):
      self.name = name

  # proxy the 'comment' attribute from the 'comment_object' relationship
  @property
  def comment(self):
      if self.comment_object is None:
          return ""
      else:
          return self.comment_object.comment

  @comment.setter
  def comment(self, value):
      if self.comment_object is None:
          self.comment_object = Comment()
      self.comment_object.comment = value
2 голосов
/ 31 января 2012

Попробуйте это

import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy import Column, Integer, Text, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy

Base = declarative_base()

class User(Base):
  __tablename__ = 'users'
  id = Column(Integer, primary_key=True)
  name = Column(Text)

  def __init__(self, name):
      self.name = name

  # proxy the 'comment' attribute from the 'comment_object' relationship
  comment = association_proxy('comment_object', 'comment')


class Comment(Base):
  __tablename__ = 'comments'
  id = Column(Integer, primary_key=True)
  comment = Column('comment', Text, nullable=False, default="")
  user_id = Column(ForeignKey('users.id'), nullable=False)

  def __init__(self, comment):
      self.comment = comment

  user_object = orm.relationship(
      "User",
      backref=orm.backref('comment_object'),
      uselist=False
      )

if __name__ == "__main__":
  engine = sa.create_engine('sqlite:///:memory:', echo=True)
  Session = orm.sessionmaker(bind=engine)
  Base.metadata.create_all(engine)
  session = Session()
  u = User(name="Max Mueller")
# comment = Comment("")
# comment.user_object = u

# session.add(u)
# session.commit()
  print "SS :", u
  print u.comment

Вы дали uselist в backref, что должно быть в relationship.

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