SQLAlchemy 1.0.13에서 Flask-SQLAlchemy 2.1을 사용하고 있는데, 다음과 같이 Address
및 Customer
, 서로 여러 관계를 가질 수 :Flask-SQLAlchemy : CircularDependencyError 여기서 다 대일 관계의 같은 행은 동일한 테이블과 일대 다 관계가 될 수 있습니다.
class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
... # Other rows including first_name, last_name, etc.
customer_id = db.Column(
db.Integer,
db.ForeignKey('customers.id')
)
customer = db.relationship(
'Customer',
foreign_keys=customer_id,
back_populates='addresses'
)
class Customer(db.Model):
id = db.Column(db.Integer, primary_key=True)
billing_address_id = db.Column(db.Integer, db.ForeignKey('addresses.id'))
billing_address = db.relationship(
'Address',
foreign_keys=billing_address_id
)
shipping_address_id = db.Column(
db.Integer,
db.ForeignKey('addresses.id')
)
shipping_address = db.relationship(
'Address',
foreign_keys=shipping_address_id
)
addresses = db.relationship(
'Address',
foreign_keys='Address.customer_id',
back_populates='customer'
)
자동으로 Customer
인스턴스에 대한 어떤 addresses
에 billing_address
또는 shipping_address
을 설정 추가 두 개의 이벤트 리스너도 있습니다
@event.listens_for(Customer.billing_address, 'set')
def add_billing_address_event(target, value, oldvalue, initiator):
"""If a billing address is added to a `Customer`, add it to addresses."""
if value is not None and value not in target.addresses:
target.addresses.append(value)
@event.listens_for(Customer.shipping_address, 'set')
def add_shipping_address_event(target, value, oldvalue, initiator):
"""If a shipping address is added to `Customer`, add to addresses."""
if value is not None and value not in target.addresses:
target.addresses.append(value)
,536,913,632가 나는 이벤트 리스너를 주석 경우,이 내가 무엇을 기대 또한 인은
CircularDependencyError
가 발생하지 않습니다
> c = Customer()
> c.billing_address = Address(first_name='Bill')
> c.shipping_address = Address(first_name='Ship')
> db.session.add(c)
> db.session.flush()
CircularDependencyError: Circular dependency detected. (ProcessState(ManyToOneDP(Customer.shipping_address), <Customer at 0x7f53aa5c9fd0>, delete=False), ProcessState(ManyToOneDP(Address.customer), <Address at 0x7f53aa4e4128>, delete=False), ProcessState(ManyToOneDP(Address.customer), <Address at 0x7f53aa4e4080>, delete=False), SaveUpdateState(<Customer at 0x7f53aa5c9fd0>), ProcessState(ManyToOneDP(Customer.billing_address), <Customer at 0x7f53aa5c9fd0>, delete=False), ProcessState(OneToManyDP(Customer.addresses), <Customer at 0x7f53aa5c9fd0>, delete=False), SaveUpdateState(<Address at 0x7f53aa4e4080>), SaveUpdateState(<Address at 0x7f53aa4e4128>))
Customer.address
로 : 나는 기대로 CircularDependencyError
에 Customer.billing_address
및 Customer.shipping_address
결과를 설정하려고 10
액세스 할 수 없습니다. 그러나 이것은 동일한 Address
인스턴스가 billing_address
또는 shipping_address
및 addresses
에 존재하는 것으로 인해 순환 종속성이 발생하므로 addresses
에 현재 청구서 수신 주소와 배송 주소가 포함되도록 허용하고 싶습니다. 그러나
class Address(db.Model):
...
customer_id = db.Column(
db.Integer,
db.ForeignKey('customers.id', name='fk_customer_id')
)
customer = db.relationship(
'Customer',
foreign_keys=customer_id,
back_populates='addresses',
post_update=True
)
이 여전히 CircularDependencyError
제기 :
relevant SQLAlchemy docs에 따르면,이 관계 post_update=True
인수 한쪽을 첨가하고, 그 외부 키 이름을 부여하여 정착되어야
CircularDependencyError: Circular dependency detected. (ProcessState(OneToManyDP(Customer.addresses), <Customer at 0x7f620af3ff60>, delete=False), SaveUpdateState(<Address at 0x7f620ae5a080>), SaveUpdateState(<Address at 0x7f620ae5a128>), ProcessState(ManyToOneDP(Customer.billing_address), <Customer at 0x7f620af3ff60>, delete=False), SaveUpdateState(<Customer at 0x7f620af3ff60>), ProcessState(ManyToOneDP(Customer.shipping_address), <Customer at 0x7f620af3ff60>, delete=False))
관련 StackOverflow 게시물에 언급 된 customer_id
외래 키에 use_alter=True
을 전달하려고 시도했습니다.
customer_id = db.Column(
db.Integer,
db.ForeignKey('customers.id', name='fk_customer_id', use_alter=True)
)
CircularDependencyError
이 여전히 발생합니다. 나는 아래에 게시 할 것으로 보이는 해결책을 찾았지만 올바른 해결책이라고 확신하지 못합니다. 관계의 양쪽 post_update=True
설정
"이 플래그는 하나의 관계에 배치해야"이것은 'addresses' 관계, 또는 모두'shipping_address'과'billing_address' 관계 중 어느 하나에'post_update = TRUE '로 설정하는 의미 같은 '주소'/ '고객'관계의 양면이 아닙니다. – univerio