fastapi_No.16_数据库操作

单文件格式

为了演示如何利用fastapi与数据库之间进行交互操作,先用单文件的方式进行演示,然后再基于单文件的内容将内容分为多文件格式。
如果看不懂数据库相关的操作,请先参见SQL alchemy相关的文章

1. 创建数据库常量

from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, Session
# 数据连接的url
DBURL = "mysql+pymysql://root:123456@127.0.0.1:3306/dbtest"
# 连接数据库的引擎
ENGINE = create_engine(DBURL)
# 数据库会话
SESSION = Session(ENGINE)
# 自定义数据表模型类的基类
BASE = declarative_base()

2. 定义数据表模型

from sqlalchemy import Column,Integer,String,Float,Boolean,ForeignKey
from sqlalchemy.orm import relationship
class User(BASE):
#表名
	__tablename__ = "users"
	id = Column(Integer, primary_key=True, autoincrement=True)
	email = Column(String(200),unique=True)
	hashed_password = Column(String(200))
	is_active = Column(Boolean, default=True)
	items = relationship("Item", back_polulates="owner")

class Item(BASE):
	__tablename__ = "items"
	id = Column(Integer,primary_key=True,autoincrement=True)
	title = Column(String(20))
	description = Column(String(255))
	owner_id = Column(Integer,ForeignKey("users.id"))
	owner = relationship("User",back_populates="items")

3. 定义验证模型

from typing import List,Union
from pydantic import BaseModel
class ItemBase(BaseModel):
	title:str
	description:Union[str,None] = None
class ItemCreate(ItemBase):
	pass
class ItemIn(ItemBase):
	id:int
	owner_id:int
	class Config:
		orm_mode = True
class UserBase(BaseModel):
	email:str
class UserCreate(UserBase):
	password:str
class UserIn(UserBase):
	id:int
	is_active:bool
	items:List[ItemIn] = []
	class Config:
	# orm_mode即可以以data['id']又可以以data.id方式获取数据
		orm_mode = True

4. 创建CRUD函数

def get_user(db:Session,user_id:int):
	return db.query(User).filter(User.id == user_id).first()
def get_user_by_email(db:Session,email:str):
	return db.query(User).filter(User.email == email).first()
def get_users(db:Session,skip:int =0,limit:int=100):
	return db.query(User).offset(skip).limit(limit).all()
def create_user(db:Session,user:UserCreate):
	faked_hashed_password = user.password + "notreallyhashed"
	db_user = User(email=user.email,hashed_password=faked_hashed_password)
	db.add(db_user)
	db.commit()
	# 将数据库自定义的列添加到db_user中,如id
	db.refresh(db_user)
	return db_user
	
def get_items(db:Session,skip:int=0,limit:int=100):
	return db.query(Item).offset(skip).limit(limit).all()
def create_user_item(db:Session,item:ItemCreate,user_id:int):
	db_item = Item(**item.dict(),owner_id=user_id)
	db.add(db_item)
	db.commit()
	db.refresh(db_item)
	return db_item

5. 创建API

from typing import List
from fastapi import Depends,FastAPI,HTTPException
# 创建所有数据表
BASE.metadata.create_all(ENGINE)

app = FastAPI()
# 定义依赖项
def get_db():
	db = Session(ENGINE)
	try:
		yield db
	finally:
		db.close()
		
@app.post("/users/", response_model=UserIn)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    db_user = get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return create_user(db=db, user=user)

@app.get("/users/", response_model=List[UserIn])
def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    users = get_users(db, skip=skip, limit=limit)
    return users

@app.get("/users/{user_id}", response_model=UserIn)
def read_user(user_id: int, db: Session = Depends(get_db)):
    db_user = get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user

@app.post("/users/{user_id}/items/", response_model=ItemIn)
def create_item_for_user(
    user_id: int, item: ItemCreate, db: Session = Depends(get_db)
):
    return create_user_item(db=db, item=item, user_id=user_id)
    
@app.get("/items/", response_model=List[ItemIn])
def read_items(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    items = get_items(db, skip=skip, limit=limit)
    return items

6. 调试代码

if __name__ == "__main__":
	import uvicorn
	uvicorn.run(app,host="127.0.0.1",port=8080)

完整代码

from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, Session

DBURL = "mysql+pymysql://root:123456@127.0.0.1:3306/testdb"
ENGINE = create_engine(DBURL)
SESSION = Session(ENGINE)
BASE = declarative_base()

from sqlalchemy import Column,Integer,String,Float,Boolean,ForeignKey
from sqlalchemy.orm import relationship
class User(BASE):
	__tablename__ = "users"
	id = Column(Integer, primary_key=True, autoincrement=True)
	email = Column(String(200),unique=True)
	hashed_password = Column(String(200))
	is_active = Column(Boolean, default=True)
	items = relationship("Item", back_populates="owner")

class Item(BASE):
	__tablename__ = "items"
	id = Column(Integer,primary_key=True,autoincrement=True)
	title = Column(String(20))
	description = Column(String(255))
	owner_id = Column(Integer,ForeignKey("users.id"))
	owner = relationship("User",back_populates="items")

from typing import List,Union
from pydantic import BaseModel
class ItemBase(BaseModel):
	title:str
	description:Union[str,None] = None
class ItemCreate(ItemBase):
	pass
class ItemIn(ItemBase):
	id:int
	owner_id:int
	class Config:
		orm_mode = True
class UserBase(BaseModel):
	email:str
class UserCreate(UserBase):
	password:str
class UserIn(UserBase):
	id:int
	is_active:bool
	items:List[ItemIn] = []
	class Config:
	# orm_mode即可以以data['id']又可以以data.id方式获取数据
		orm_mode = True

def get_user(db:Session,user_id:int):
	return db.query(User).filter(User.id == user_id).first()
def get_user_by_email(db:Session,email:str):
	return db.query(User).filter(User.email == email).first()
def get_users(db:Session,skip:int =0,limit:int=100):
	return db.query(User).offset(skip).limit(limit).all()
def create_user(db:Session,user:UserCreate):
	faked_hashed_password = user.password + "notreallyhashed"
	db_user = User(email=user.email,hashed_password=faked_hashed_password)
	db.add(db_user)
	db.commit()
	# 将数据库自定义的列添加到db_user中,如id
	db.refresh(db_user)
	return db_user

def get_items(db:Session,skip:int=0,limit:int=100):
	return db.query(Item).offset(skip).limit(limit).all()
def create_user_item(db:Session,item:ItemCreate,user_id:int):
	db_item = Item(**item.dict(),owner_id=user_id)
	db.add(db_item)
	db.commit()
	db.refresh(db_item)
	return db_item

from typing import List
from fastapi import Depends,FastAPI,HTTPException
# 创建所有数据表
BASE.metadata.create_all(ENGINE)

app = FastAPI()
# 定义依赖项
def get_db():
	db = Session(ENGINE)
	try:
		yield db
	finally:
		db.close()
		
@app.post("/users/", response_model=UserIn)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    db_user = get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return create_user(db=db, user=user)

@app.get("/users/", response_model=List[UserIn])
def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    users = get_users(db, skip=skip, limit=limit)
    return users

@app.get("/users/{user_id}", response_model=UserIn)
def read_user(user_id: int, db: Session = Depends(get_db)):
    db_user = get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user

@app.post("/users/{user_id}/items/", response_model=ItemIn)
def create_item_for_user(
    user_id: int, item: ItemCreate, db: Session = Depends(get_db)
):
    return create_user_item(db=db, item=item, user_id=user_id)

@app.get("/items/", response_model=List[ItemIn])
def read_items(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    items = get_items(db, skip=skip, limit=limit)
    return items

if __name__ == "__main__":
	import uvicorn
	uvicorn.run(app,host="127.0.0.1",port=8080)

由此可以看出将所有的信息存放在单文件中,不利于代码的维护。

多文件格式

在这种情况下,通常会将单文件根据各个结构存放在不同的文件中。文件结构如下:
|config.py --数据库基础配置文件
|models.py --数据库数据表类
|schemas.py --数据验证类
|services.py --数据表的增删改查
|main.py --接口类
这里就不做详细的示范,详细可参考下一篇文章[大型应用开发]。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习_程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值