How to extend the getter function of SQLAlchemy association_proxy?

Edit: I would like to simulate a 1 to 0:1 relationship between User and Comment (a user can have zero or one comment). Instead of accessing the Comment object, I would like to directly access the comment itself. Using SQLAlchemys association_proxy great for this scenario except : to access User.comment before linking Comment . But in this case, I would rather expect None instead of AttributeError .

Take a look at the following example:

 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() 

Now the following code throws an AttributeError :

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

What would be the best way to catch this exception and instead specify a default value (for example, an empty string)?

+2
source share
2 answers

You do not need association_proxy . You could do just fine with a regular property . AttributeError raised (because None ) because there is no dependent row, and None does not have a comment attribute.

 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 
+3
source

try it

 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 

You gave uselist in backref , which should be in a relationship .

+2
source

Source: https://habr.com/ru/post/1403694/


All Articles