Technology Sharing

FastAPI Learning Road (34) Database Multi-Table Operation

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Previously, we shared the operation of database tables based on a single table. When we designed the database, we also designed cross-table operations. Let's take a look at the design of the database.

  1. class User(Base):
  2. __tablename__ = "users"
  3. id = Column(Integer, primary_key=True, index=True)
  4. email = Column(String(10), unique=True, index=True)
  5. hashed_password = Column(String(100))
  6. is_active = Column(Boolean, default=True)
  7. items = relationship("Item", back_populates="owner")
  8. class Item(Base):
  9. __tablename__ = "items"
  10. id = Column(Integer, primary_key=True, index=True)
  11. title = Column(String(10), index=True)
  12. description = Column(String(10), index=True)
  13. owner_id = Column(Integer, ForeignKey("users.id"))
  14. owner = relationship("User", back_populates="items")

Next, let's look at the complete code

  1. from typing import Optional, List
  2. """
  3. 数据库多表操作
  4. """
  5. from sqlalchemy import create_engine, ForeignKey
  6. from sqlalchemy.orm import declarative_base
  7. from sqlalchemy.orm import sessionmaker, relationship
  8. from sqlalchemy import Column, Integer, String, Boolean
  9. conn = "mysql+pymysql://{username}:{password}@{host}:{port}/{database}?charset=utf8".format(
  10. username="root", password="123456", host="10.30.10.36", port=3306, database="fastapi_learn_road")
  11. engine = create_engine(conn)
  12. # 该类的每个实例都是一个数据库会话,该类本身还不是数据库会话,但是一旦我们创建了SessionLocal的实例,这个实例将是实际的数据库会话
  13. SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  14. # 创建数据库基类
  15. Base = declarative_base()
  16. # 创建两个数据库模型,继承自Base基类
  17. class User(Base):
  18. __tablename__ = "users"
  19. id = Column(Integer, primary_key=True, index=True)
  20. email = Column(String(10), unique=True, index=True)
  21. hashed_password = Column(String(100))
  22. is_active = Column(Boolean, default=True)
  23. items = relationship("Item", back_populates="owner")
  24. class Item(Base):
  25. __tablename__ = "items"
  26. id = Column(Integer, primary_key=True, index=True)
  27. title = Column(String(10), index=True)
  28. description = Column(String(10), index=True)
  29. owner_id = Column(Integer, ForeignKey("users.id"))
  30. owner = relationship("User", back_populates="items")
  31. from pydantic import BaseModel
  32. from sqlalchemy.orm import Session
  33. from fastapi import FastAPI, Depends, HTTPException
  34. def create_db():
  35. """每个请求处理完毕后关闭当前连接,不同的请求使用不同的链接"""
  36. db = SessionLocal()
  37. try:
  38. yield db
  39. finally:
  40. db.close()
  41. app = FastAPI()
  42. # -------------------------以下是多表操作
  43. class BaseItem(BaseModel):
  44. title: str
  45. description: Optional[str] = None
  46. class ItemModel(BaseItem):
  47. pass
  48. class ItemOut(BaseItem):
  49. id: int
  50. owner_id: int
  51. class Config:
  52. orm_mode = True
  53. @app.post("/items/{uid}", response_model=ItemOut)
  54. def create_item_by_user(uid: int, item: ItemModel, db: Session = Depends(create_db)):
  55. init_item = Item(**item.dict(), owner_id=uid)
  56. db.add(init_item)
  57. db.commit()
  58. db.refresh(init_item)
  59. return init_item
  60. # 分页获取所有的items
  61. @app.get("/items", response_model=List[ItemOut])
  62. def get_items(skip: int = 0, limit: int = 10, db: Session = Depends(create_db)):
  63. return db.query(Item).offset(skip).limit(limit).all()
  64. # 如何查询用户的items
  65. @app.get("/items/{uid}", response_model=List[ItemOut])
  66. def get_items_by_uid(uid: int, db: Session = Depends(create_db)):
  67. user = db.query(User).filter(User.id==uid).first()
  68. if not user:
  69. raise HTTPException(status_code=200, detail="this user is not valid")
  70. return db.query(Item).filter(Item.owner==user).offset(0).limit(2).all()

Postman requests to create an item

Query all items

Query the items of a specified user

We have implemented a simple multi-table query.