I am hoping for some guidance about what I believe is going to be a common pattern in SQLAlchemy for Python. However, I have so far failed to find a simple explanation for someone new to SQLAlchemy.
I have the follow objects:
- Customers
- Orders
- Products
I am building a Python FastAPI application and I want to be able to create customers, and products individually. And subsequently, I want to then be able to create an order for a customer that can contain 1 or more products. A customer will be able to have multiple orders also.
Here are my SQLAlchemy models:
order_products = Table('order_products', Base.metadata,
Column('order_id', ForeignKey('orders.id'), primary_key=True),
Column('product_id', ForeignKey('products.id'), primary_key=True)
)
class Customer(Base):
__tablename__ = "customers"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
address = Column(String)
phonenumber = Column(String)
email = Column(String, unique=True, index=True)
is_active = Column(Boolean, default=True)
orders = relationship("Order", back_populates="customers")
class Order(Base):
__tablename__ = "orders"
id = Column(Integer, primary_key=True, index=True)
ordernumber = Column(String, index=True)
customer_id = Column(Integer, ForeignKey("customers.id"))
customers = relationship("Customer", back_populates="orders")
products = relationship("Product", secondary="order_products", back_populates="orders")
class Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
size = Column(Integer)
order_id = Column(Integer, ForeignKey("orders.id"))
orders = relationship("Order", secondary="order_products", back_populates="products")
And here are my CRUD operations:
def create_customer(db: Session, customer: customer.CustomerCreate):
db_customer = models.Customer(name = customer.name, address = customer.address, email=customer.email, phonenumber=customer.phonenumber)
db.add(db_customer)
db.commit()
db.refresh(db_customer)
return db_customer
def create_product(db: Session, product: product.Productreate):
db_product = models.Product(name = product.name, size = product.size)
db.add(db_product)
db.commit()
db.refresh(db_product)
return db_product
def create_order(db: Session, order: order.OrderCreate, cust_id: int):
db_order = models.Order(**order.dict(), customer_id=cust_id)
db.add(db_order)
db.commit()
db.refresh(db_order)
return db_order
def update_order_with_product(db: Session, order: order.Order):
db_order = db.query(models.Order).filter(models.Order.id==1).first()
if db_order is None:
return None
db_product = db.query(models.Order).filter(models.Product.id==1).first()
if db_order is None:
return None
db_order.products.append(db_product)
db.add(db_order)
db.commit()
db.refresh(db_order)
return db_order
All of the CRUD operations work apart from update_order_with_product which gives me this error:
child_impl = child_state.manager[key].impl KeyError: 'orders'
I'm not sure if I am taking the correct approach to the pattern needed to define the relationships between my models. If not, can someone point me in the right direction of some good examples for a beginner?
If my pattern is valid then there must be an issue with my CRUD operation trying to create the relationships? Can anyone help with that?