SQLAlchemy에서 하나의 매핑된 클래스에 여러 외래 키를 동일한 기본 키에 매핑하는 방법
예제:
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(255))
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
street_address = Column(String(255))
city = Column(String(255))
state = Column(String(255))
postal_code = Column(String(255))
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship(User) # 'user' 속성을 통해 User 인스턴스에 액세스할 수 있습니다.
class BillingAddress(Address):
__tablename__ = 'billing_addresses'
# billing_address 테이블은 address 테이블의 모든 컬럼을 상속받습니다.
# 추가 컬럼을 정의할 수도 있습니다.
class ShippingAddress(Address):
__tablename__ = 'shipping_addresses'
# shipping_address 테이블은 address 테이블의 모든 컬럼을 상속받습니다.
# 추가 컬럼을 정의할 수도 있습니다.
user = User(name='John Doe')
user.address = Address(street_address='123 Main St', city='Anytown', state='CA', postal_code='94101')
user.billing_address = BillingAddress(street_address='456 Elm St', city='Anytown', state='CA', postal_code='94101')
user.shipping_address = ShippingAddress(street_address='789 Oak St', city='Anytown', state='CA', postal_code='94101')
# user 인스턴스를 저장합니다.
session.add(user)
session.commit()
위 예제에서 Address
테이블은 user_id
외래 키를 사용하여 User
테이블의 id
기본 키를 참조합니다. BillingAddress
및 ShippingAddress
클래스는 Address
클래스에서 상속되므로 user_id
외래 키를 그대로 상속받습니다.
따라서 하나의 User
인스턴스는 billing_address
및 shipping_address
속성을 통해 BillingAddress
및 ShippingAddress
인스턴스 두 개를 참조할 수 있습니다.
참고:
- 다중 외래 키를 사용할 때는 참조하는 테이블의 기본 키가 고유해야 합니다.
- 다중 외래 키는 관계의 다대다 관계를 나타낼 수 있습니다.
- SQLAlchemy는 다중 외래 키를 사용하여 더 복잡한 관계를 모델링하기 위한 여러 기능을 제공합니다. 자세한 내용은 SQLAlchemy 문서를 참조하십시오.
SQLAlchemy 예제 코드: 다중 외래 키를 사용한 관계 매핑
설치
먼저 프로젝트에 필요한 Python 패키지를 설치해야 합니다. 다음 명령을 사용하여 설치할 수 있습니다.
pip install sqlalchemy psycopg2
코드
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base, relationship
# 데이터베이스 엔진 생성
engine = create_engine("postgresql://user:password@host:port/database")
# 기본 클래스 정의
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String(255))
class Address(Base):
__tablename__ = "addresses"
id = Column(Integer, primary_key=True)
street_address = Column(String(255))
city = Column(String(255))
state = Column(String(255))
postal_code = Column(String(255))
user_id = Column(Integer, ForeignKey("users.id"))
user = relationship(User) # 'user' 속성을 통해 User 인스턴스에 액세스할 수 있습니다.
class BillingAddress(Address):
__tablename__ = "billing_addresses"
# billing_address 테이블은 address 테이블의 모든 컬럼을 상속받습니다.
# 추가 컬럼을 정의할 수도 있습니다.
class ShippingAddress(Address):
__tablename__ = "shipping_addresses"
# shipping_address 테이블은 address 테이블의 모든 컬럼을 상속받습니다.
# 추가 컬럼을 정의할 수도 있습니다.
# 테이블 생성
Base.metadata.create_all(engine)
# 사용자, 주소, 결제 주소 및 배송 주소 만들기
user = User(name="John Doe")
user.address = Address(
street_address="123 Main St", city="Anytown", state="CA", postal_code="94101"
)
user.billing_address = BillingAddress(
street_address="456 Elm St", city="Anytown", state="CA", postal_code="94101"
)
user.shipping_address = ShippingAddress(
street_address="789 Oak St", city="Anytown", state="CA", postal_code="94101"
)
# 세션에 사용자 추가 및 커밋
session = create_session(bind=engine)
session.add(user)
session.commit()
# 사용자 및 관련된 주소 가져오기
user = session.query(User).first()
print(f"사용자 이름: {user.name}")
print(f"주소: {user.address}")
print(f"결제 주소: {user.billing_address}")
print(f"배송 주소: {user.shipping_address}")
이 코드는 다음과 같은 작업을 수행합니다.
create_engine
함수를 사용하여 PostgreSQL 데이터베이스에 대한 SQLAlchemy 엔진을 생성합니다.declarative_base
함수를 사용하여 기본 클래스를 위한 메타데이터를 정의합니다.User
,Address
,BillingAddress
및ShippingAddress
클래스를 정의합니다.relationship
속성을 사용하여User
및Address
테이블 간의 관계를 정의합니다.BillingAddress
및ShippingAddress
클래스는Address
클래스에서 상속됩니다.metadata.create_all
메서드를 사용하여 데이터베이스에 테이블을 생성합니다.session.add
메서드를 사용하여 세션에 사용자를 추가합니다.session.commit
메서드를 사용하여 변경 사항을 커밋합니다.session.query
를 사용하여 사용자 및 관련된 주소를 가져옵니다.- 사용자
SQLAlchemy에서 하나의 매핑된 클래스에 여러 외래 키를 동일한 기본 키에 매핑하는 대체 방법
다중 합성 외래 키 사용:
이 방법은 여러 컬럼으로 구성된 외래 키를 사용하는 것입니다. 예를 들어 다음과 같이 user_id
및 address_type
컬럼으로 구성된 합성 외래 키를 사용할 수 있습니다.
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
street_address = Column(String(255))
city = Column(String(255))
state = Column(String(255))
postal_code = Column(String(255))
user_id = Column(Integer)
address_type = Column(String(255))
user = relationship(User, foreign_keys=[user_id, address_type])
위 코드에서 user
관계는 user_id
및 address_type
컬럼을 사용하여 User
테이블을 참조합니다.
별도의 테이블 사용:
이 방법은 각 유형의 주소에 대해 별도의 테이블을 만드는 것입니다. 예를 들어 다음과 같이 billing_addresses
및 shipping_addresses
테이블을 만들 수 있습니다.
class BillingAddress(Base):
__tablename__ = 'billing_addresses'
id = Column(Integer, primary_key=True)
street_address = Column(String(255))
city = Column(String(255))
state = Column(String(255))
postal_code = Column(String(255))
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship(User)
class ShippingAddress(Base):
__tablename__ = 'shipping_addresses'
id = Column(Integer, primary_key=True)
street_address = Column(String(255))
city = Column(String(255))
state = Column(String(255))
postal_code = Column(String(255))
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship(User)
위 코드에서 BillingAddress
및 ShippingAddress
클래스는 별도의 테이블을 사용하지만 user_id
외래 키를 사용하여 User
테이블을 참조합니다.
뷰 사용:
이 방법은 가상의 테이블을 만드는 뷰를 사용하는 것입니다. 예를 들어 다음과 같이 user_addresses
뷰를 만들 수 있습니다.
CREATE VIEW user_addresses AS
SELECT
a.id,
a.street_address,
a.city,
a.state,
a.postal_code,
a.user_id,
CASE
WHEN a.address_type = 'billing' THEN 'billing'
WHEN a.address_type = 'shipping' THEN 'shipping'
ELSE NULL
END AS address_type
FROM addresses a;
위 코드에서 user_addresses
뷰는 addresses
테이블의 데이터를 기반으로 가상의 테이블을 만듭니다.
그런 다음 SQLAlchemy에서 다음과 같이 user_addresses
뷰를 매핑할 수 있습니다.
class UserAddress(Base):
__tablename__ = 'user_addresses' # 뷰 이름 사용
id = Column(Integer, primary_key=True)
street_address = Column(String(255))
city = Column(String(255))
state = Column(String(255))
postal_code = Column(String(255))
user_id = Column(Integer)
address_type = Column(String(255))
user = relationship(User)
위 코드에서 UserAddress
클래스는 user_addresses
뷰를 매핑하고 user
관계를 사용하여 User
테이블을 참조합니다.
python postgresql sqlalchemy