我什么时候需要使用 sqlalchemy back_populates? [英] When do I need to use sqlalchemy back_populates?

查看:50
本文介绍了我什么时候需要使用 sqlalchemy back_populates?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我按照本指南尝试 SQLAlchemy 关系示例时:基本关系模式

我有这个代码

#!/usr/bin/env python# 编码:utf-8从 sqlalchemy 导入 create_engine从 sqlalchemy 导入表、列、整数、外键来自 sqlalchemy.orm 的导入关系,sessionmaker从 sqlalchemy.ext.declarative 导入 declarative_baseengine = create_engine('sqlite:///:memory:', echo=True)会话 = sessionmaker(绑定=引擎)会话 = 会话()Base = declarative_base(bind=engine)父类(基类):__表名__ = '父'id = 列(整数,primary_key=True)孩子 = 关系(孩子")类儿童(基础):__表名__ = '孩子'id = 列(整数,primary_key=True)parent_id = Column(Integer, ForeignKey('parent.id'))父母=关系(父母")Base.metadata.create_all()p = 父()session.add(p)session.commit()c = 孩子(parent_id=p.id)session.add(c)session.commit()打印孩子:{}".format(p.children[0].id)打印父母:{}".格式(c.parent.id)

效果很好,但在指南中,它说模型应该是:

class Parent(Base):__表名__ = '父'id = 列(整数,primary_key=True)**孩子 = 关系(孩子",back_populates =父母")**类儿童(基础):__表名__ = '孩子'id = 列(整数,primary_key=True)parent_id = Column(Integer, ForeignKey('parent.id'))**父=关系(父",back_populates =孩子")**

为什么在我的示例中不需要 back_populatesbackref ?我什么时候应该使用其中一种?

解决方案

如果使用 backref 则不需要在第二个表上声明关系.

class Parent(Base):__表名__ = '父'id = 列(整数,primary_key=True)孩子 = 关系(孩子",backref =父母")类儿童(基础):__表名__ = '孩子'id = 列(整数,primary_key=True)parent_id = Column(Integer, ForeignKey('parent.id'))

如果您使用backref,并单独定义关系,那么如果您不使用back_populates,sqlalchemy 不会知道连接关系,所以修改一个也会修改另一个.

因此,在您的示例中,您单独定义了 relationship,但未提供 back_populates 参数,因此不会自动修改一个字段更新交易中的另一个.

<预><代码>>>>父母 = 父母()>>>孩子 = 孩子()>>>child.parent = 父母>>>打印(父母.孩子)[]

看看它是如何没有自动填写 children 字段的?

现在,如果您提供 back_populates 参数,sqlalchemy 将连接这些字段.

class Parent(Base):__表名__ = '父'id = 列(整数,primary_key=True)孩子 = 关系(孩子",back_populates =父母")类儿童(基础):__表名__ = '孩子'id = 列(整数,primary_key=True)parent_id = Column(Integer, ForeignKey('parent.id'))父母=关系(父母",back_populates =孩子")

所以现在我们得到

<预><代码>>>>父母 = 父母()>>>孩子 = 孩子()>>>child.parent = 父母>>>打印(父母.孩子)[孩子(...)]

Sqlalchemy 现在知道这两个字段是相关的,并且会随着另一个字段的更新而更新.值得注意的是,使用 backref 也可以做到这一点.如果你想在每个类上定义关系,使用 back_populates 是很好的,所以很容易看到所有字段只看模型类,而不必查看其他定义字段的类通过反向引用.

When I try SQLAlchemy Relation Example following this guide: Basic Relationship Patterns

I have this code

#!/usr/bin/env python
# encoding: utf-8
from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(bind=engine)

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent")

Base.metadata.create_all()

p = Parent()
session.add(p)
session.commit()
c = Child(parent_id=p.id)
session.add(c)
session.commit()
print "children: {}".format(p.children[0].id)
print "parent: {}".format(c.parent.id)

It works well, but in the guide, it says the model should be:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    **children = relationship("Child", back_populates="parent")**

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    **parent = relationship("Parent", back_populates="children")**

Why don't I need back_populates or backref in my example? When should I use one or the other?

解决方案

If you use backref you don't need to declare the relationship on the second table.

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", backref="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))

If you're not using backref, and defining the relationship's separately, then if you don't use back_populates, sqlalchemy won't know to connect the relationships, so that modifying one also modifies the other.

So, in your example, where you've defined the relationship's separately, but didn't provide a back_populates argument, modifying one field wouldn't automatically update the other in your transaction.

>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[]

See how it didn't automatically fill out the children field?

Now, if you supply a back_populates argument, sqlalchemy will connect the fields.

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", back_populates="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent", back_populates="children")

So now we get

>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[Child(...)]

Sqlalchemy knows these two fields are related now, and will update each as the other is updated. It's worth noting that using backref will do this, too. Using back_populates is nice if you want to define the relationships on every class, so it's easy to see all the fields just be glancing at the model class, instead of having to look at other classes that define fields via backref.

这篇关于我什么时候需要使用 sqlalchemy back_populates?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆