Python 2.7 SQLAlchemy以(1到0..1)关系连接两个表

Python 2.7 SQLAlchemy以(1到0..1)关系连接两个表,python-2.7,flask,sqlalchemy,Python 2.7,Flask,Sqlalchemy,我有两个(1到0..1)关系的表: 型号.py # -------------------------------------------------- class Person(db.Model): __tablename__ = 'person' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False) address = db.Colum

我有两个(1到0..1)关系的表:

型号.py

# --------------------------------------------------
class Person(db.Model):
    __tablename__ = 'person'
    id = db.Column(db.Integer, primary_key=True)

    name = db.Column(db.String, nullable=False)
    address = db.Column(db.String, nullable=False)  

# --------------------------------------------------
class Gift(db.Model):
    __tablename__ = 'gift'
    id = db.Column(db.Integer, primary_key=True)

    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
    person = relationship("Person", uselist=False, backref="gift")

    gift_idea = db.Column(db.String, nullable=False)

# --------------------------------------------------
    a = session.query(Gift).join(Person)
问题:

  • 我的一对一表格的结构正确吗?我知道在SQLAlchemy文档中,关系代码行(person=relationship…)在父类中,但我需要它在子类中,可以吗

  • 我的目标是显示(来自礼物表的礼物想法)和(来自人表的人姓名、人地址),如果这个人有礼物想法。在我的搜索中,我发现人们使用query.join来获取这些信息,我尝试了很多代码,但下面的语句至少为我提供了我所需要的内容的一半 需要:

  • 视图.py

    # --------------------------------------------------
    class Person(db.Model):
        __tablename__ = 'person'
        id = db.Column(db.Integer, primary_key=True)
    
        name = db.Column(db.String, nullable=False)
        address = db.Column(db.String, nullable=False)  
    
    # --------------------------------------------------
    class Gift(db.Model):
        __tablename__ = 'gift'
        id = db.Column(db.Integer, primary_key=True)
    
        person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
        person = relationship("Person", uselist=False, backref="gift")
    
        gift_idea = db.Column(db.String, nullable=False)
    
    # --------------------------------------------------
    
        a = session.query(Gift).join(Person)
    
    你能帮我回答我的问题吗?谢谢你的努力

  • 为了从子端定义正确的1到[0..1]关系,必须确保
    backref
    设置了
    uselist=False
    ,而默认情况下从子端到父端的
    uselist
    将为
    False

    person = db.relationship(
        "Person",
        backref=db.backref("gift", uselist=False),
    )
    
  • 那么查询非常简单:

    a = (session
         .query(
             Gift.gift_idea,
             Person.name.label("person_name"),
             Person.address.label("person_address"),
         )
         # .select_from(Gift)  # @note: optional, but will need it if the first column in the `.query(...)` above will be from table `Person`
         .join(Person)
         )
    

  • 根据sqlalchemy一对一关系模式定义

    一对一本质上是与标量的双向关系 两面都有属性。为了实现这一点,uselist标志指示 将标量属性而不是集合放置在 关系的“许多”方面

    在你的例子中,你已经通过给出“uselist=False”禁用了礼物的“uselist”(实际上默认情况下它会被禁用)。但是你没有为个人禁用“uselist”。因为这个人仍然可以持有礼物清单(一人-许多礼物)

    您可以通过两种方式获得一对一映射

    1:使用
    backref
    函数,该函数为反面提供参数。让你的人保持原样

    class Gift(db.Model):
        __tablename__ = 'gift'
        id = db.Column(db.Integer, primary_key=True)
    
        person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
        person = relationship("Person", backref=backref("gift", uselist=False))
    
        gift_idea = db.Column(db.String, nullable=False)
    
    2:在两侧添加标量属性,而不是使用backref属性

    class Gift(db.Model):
        __tablename__ = 'gift'
        id = db.Column(db.Integer, primary_key=True)
    
        person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
        gift_idea = db.Column(db.String, nullable=False)
        person = relationship("Person")
    
    # -----------------------------------------------
    
    class Person(db.Model):
        __tablename__ = 'person'
        id = db.Column(db.Integer, primary_key=True)
    
        name = db.Column(db.String, nullable=False)
        address = db.Column(db.String, nullable=False)
        gift = relationship("Gift", uselist=False)
    
    问题2的解决方案:

    @瓦尔:给了你一个简单的解决办法。。您还可以尝试使用延迟加载,而不是通过orm查询清楚地编写所有内容

    list_of_gift_object = session.query(Gift).join(Person).all()
    
    可能您可以迭代列表,并使用“礼物人”属性来获取相关人员数据

    for gift in list_of_gift_object:
        print gift.gift_idea, gift.person.name, gift.person.address
    

    我无法感谢您enugh@gsb eng,您的解释解释了代码的含义。关于第二季度的解决方案,我尝试过,但它仍然只打印一个表数据。“van”代码中的标签显示了数据。@Aseel这很有趣,我不确定您是如何尝试的,但如果您仍然想尝试检查此()@Aseel BTW关系非常适用于延迟加载,这里的检查提示()再次感谢@gsb eng占用您的时间并与我联系,从昨天起我从您那里获得了许多有用的信息。现在,在检查了我的代码和你的代码之后,我发现了我的错误。在您的打印语句中:
    idea.person.name
    而我的{idea.name}缺少.person。!同样,在阅读了你给我的关于延迟加载的页面后,我使用了以下代码,而不是
    a=session.query(Gift).options(joinedload('person'))。all()
    ,我更喜欢它,这使我的html模板看起来更简单。