[파이썬] SQLAlchemy Polymorphic Queries

In object-oriented programming, polymorphism refers to the ability of an object to take on different forms or behaviors depending on the context in which it is used. This concept can also be applied to database queries when working with SQLAlchemy, a popular Python library for working with relational databases.

SQLAlchemy provides a powerful feature called polymorphic queries that allows you to perform queries on a base class and retrieve objects of different subclasses based on certain conditions. This can be particularly useful when working with inheritance in your database schema.

In this blog post, we will explore the basics of SQLAlchemy polymorphic queries and demonstrate how to use them in Python.

Setting up the Environment

Let’s start by setting up our development environment. Make sure you have Python and SQLAlchemy installed on your machine. You can install SQLAlchemy using the following command:

pip install sqlalchemy

Once you have SQLAlchemy installed, you can import the necessary modules and connect to your database.

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# Create an engine to connect to your database
engine = create_engine("<database_connection_uri>")

# Create a session factory
Session = sessionmaker(bind=engine)

Defining the Model

Now, let’s define a simple example model to work with. Consider a scenario where you have a base class called Animal and subclasses like Dog, Cat, and Bird. Each subclass has its own properties.

from sqlalchemy import Column, Integer, String, discriminator_column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()

class Animal(Base):
    __tablename__ = 'animals'
    id = Column(Integer, primary_key=True)
    type = Column(String(50))
    __mapper_args__ = {'polymorphic_on': type}

class Dog(Animal):
    __tablename__ = 'dogs'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))

class Cat(Animal):
    __tablename__ = 'cats'
    id = Column(Integer, primary_key=True)
    color = Column(String(50))

class Bird(Animal):
    __tablename__ = 'birds'
    id = Column(Integer, primary_key=True)
    wingspan = Column(Integer)

In this example, we have defined a base class Animal with a type column that will be used as the discriminator column in the database. The subclasses Dog, Cat, and Bird inherit from the Animal class and add their specific columns.

Querying with Polymorphic Queries

Now that we have defined our model, let’s see how we can perform polymorphic queries to retrieve objects of different subclasses.

# Create a session
session = Session()

# Query all animals
animals = session.query(Animal).all()

# Print the details of each animal
for animal in animals:
    if animal.type == 'dog':
        print(f"Dog: {animal.name}")
    elif animal.type == 'cat':
        print(f"Cat: {animal.color}")
    elif animal.type == 'bird':
        print(f"Bird: {animal.wingspan}")

In this example, we first query all objects from the Animal table. The session.query(Animal) statement retrieves all rows from the animals table, regardless of their subclass.

We then iterate over each returned object and use the type attribute to determine the specific subclass. Based on the subclass, we can access the additional properties like name, color, or wingspan.

Filtering Polymorphic Queries

Polymorphic queries become even more powerful when combined with filtering. Let’s say we want to retrieve only the dogs from our database.

dogs = session.query(Dog).all()

This query will retrieve only the rows from the dogs table, effectively filtering out the rows corresponding to cats and birds.

We can also apply additional filters to the query, like retrieving all animals with a specific color:

white_animals = session.query(Animal).filter_by(color='white').all()

This query will return all animals, regardless of their subclass, with a color value of ‘white’.

Conclusion

SQLAlchemy’s polymorphic queries feature allows you to work with hierarchical data models and retrieve objects of different subclasses based on certain conditions. This can be particularly useful when dealing with complex database schemas and inheritance.

In this blog post, we covered the basics of polymorphic queries in SQLAlchemy and demonstrated how to perform queries, filter results, and work with subclasses. I hope this introduction helps you take advantage of this powerful feature in your Python projects!