FastAPI框架学习笔记

目录结构

在这里插入图片描述

主目录下
database.py (创建数据库连接)
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "mysql+pymysql://root:123456@127.0.0.1:3306/domain_name"

engine = create_engine(SQLALCHEMY_DATABASE_URL)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()
logger.py
import logging
import ctypes

FOREGROUND_WHITE = 0x0007
FOREGROUND_BLUE = 0x01  # text color contains blue.
FOREGROUND_GREEN = 0x02  # text color contains green.
FOREGROUND_RED = 0x04  # text color contains red.
FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN

STD_OUTPUT_HANDLE = -11
std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)


def set_color(color, handle=std_out_handle):
    bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
    return bool


class Logger:
    def __init__(self, path='./logs/log.txt', clevel=logging.DEBUG, Flevel=logging.DEBUG):
        self.logger = logging.getLogger(path)
        self.logger.setLevel(logging.DEBUG)
        fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
        # 设置CMD日志
        sh = logging.StreamHandler()
        sh.setFormatter(fmt)
        sh.setLevel(clevel)
        # 设置文件日志
        fh = logging.FileHandler(path)
        fh.setFormatter(fmt)
        fh.setLevel(Flevel)
        self.logger.addHandler(sh)
        self.logger.addHandler(fh)

    def debug(self, message):
        self.logger.debug(message)

    def info(self, message):
        self.logger.info(message)

    def war(self, message, color=FOREGROUND_YELLOW):
        set_color(color)
        self.logger.warn(message)
        set_color(FOREGROUND_WHITE)

    def error(self, message, color=FOREGROUND_RED):
        set_color(color)
        self.logger.error(message)
        set_color(FOREGROUND_WHITE)

    def cri(self, message):
        self.logger.critical(message)


logger = Logger()


if __name__ == '__main__':
    logyyx = Logger('yyx.log', logging.WARNING, logging.DEBUG)
    logyyx.debug('一个debug信息')
    logyyx.info('一个info信息')
    logyyx.war('一个warning信息')
    logyyx.error('一个error信息')
    logyyx.cri('一个致命critical信息')
main.py
from fastapi import FastAPI, HTTPException, Header
from database import engine
from user import models as user_model, router as user_router


user_model.Base.metadata.create_all(bind=engine)  # 创建表

app = FastAPI()


async def get_token_header(x_token: str = Header(...)):  # 这里可以做鉴权使用
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")


app.include_router(user_router.router,
                   prefix='/users',
                   tags=['users'],
                   # dependencies=[Depends(get_token_header)],
                   responses={404: {'description': 'Not found'}})


if __name__ == '__main__':
    import uvicorn
    uvicorn.run('main:app', reload=True, host='127.0.0.1')
setting.py
from fastapi.middleware.cors import CORSMiddleware
from main import app

origins = ["*"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
User应用目录下
init.py
__all__ = ['models', 'router']
crud.py (对数据进行增删改查的操作)
from sqlalchemy.orm import Session
from user import models, schemas
from logger import logger
from datetime import datetime, timedelta
from functools import lru_cache


@lru_cache()
def get_user(db: Session, user_id: int):
    logger.debug('一个debug信息')
    logger.info('一个info信息')
    logger.war('一个warning信息')
    logger.error('一个error信息')
    logger.cri('一个致命critical信息')
    return db.query(models.User).filter(models.User.id == user_id).first()


def update_user(db: Session, user_id: int, email: str, password: str):
    db_user = db.query(models.User).filter(models.User.id == user_id).first()
    if email is None:
        db_user.email = email
    if password is None:
        db_user.hashed_password = password
    db.commit()
    db.refresh(db_user)
    return db_user


def delete_user(db: Session, user_id: int):
    # 批量删除
    db.query(models.User).filter(models.User.id == user_id).update({models.User.is_active: 0})
    db.commit()
    return {'status': 'delete success'}


def get_user_by_eamil(db: Session, email: str, query_time: datetime):
    # 模糊查询/查询修改时间在一天之前的数据
    if email:
        return db.query(models.User).filter(models.User.email.like(email + '%')).all()
    if query_time:
        return db.query(models.User).filter(models.User.update_time < query_time - timedelta(days=1), models.User.is_active == 1).all()


def batch_update_user(db: Session, update_time: datetime):
    # 根据修改时间批量更新, 类似将手动取消的所有域名恢复状态
    if update_time:
        db.query(models.User).filter(models.User.update_time > update_time).update({models.User.is_active: 1})
        db.commit()
        return db.query(models.User).filter(models.User.update_time > update_time).all()


def get_users(db: Session, skip: int = 0, limit: int = 100):
    # 分页查询
    return db.query(models.User).offset(skip).limit(limit).all()

 
def create_user(db: Session, user: schemas.UserCreate):
    fake_hashed_password = user.password + 'notreallyhashed'
    db_user = models.User(email=user.email, hashed_password=fake_hashed_password, info=user.info)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user


def get_items(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.Item).offset(skip).limit(limit).all()


def create_user_item(db: Session, item: schemas.ItemCreate, user_id: int):
    db_item = models.Item(**item.dict(), owner_id=user_id)
    db.add(db_item)
    db.commit()
    db.refresh(db_item)
    return db_item

models.py (数据模型,建表使用)
from database import Base
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, TIMESTAMP, text, JSON
from sqlalchemy.orm import relationship


class User(Base):
    __tablename__ = 'users_test'

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String(50), unique=True, index=True)
    hashed_password = Column(String(50))
    update_time = Column(TIMESTAMP(timezone=False), nullable=False)
    create_time = Column(TIMESTAMP(timezone=False), nullable=False, server_default=text('NOW()'))
    is_active = Column(Boolean, default=True)
    info = Column(JSON, nullable=True)

    items = relationship('Item', back_populates='owner')


class Item(Base):
    __tablename__ = 'items_test'

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(50), index=True)
    description = Column(String(50), index=True)
    owner_id = Column(Integer, ForeignKey('users_test.id'))

    owner = relationship('User', back_populates='items')
router.py (接口uri)
from fastapi import Depends, HTTPException, APIRouter, Body
from typing import List
from sqlalchemy.orm import Session
from datetime import datetime
from logger import logger
from user import crud, schemas
from database import SessionLocal

router = APIRouter()


def get_db():  # 在每个请求之前建立数据库连接,请求之后关闭连接,再建立一个新连接
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


@router.post('/', response_model=schemas.User, tags=['users'])
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    """
    添加用户接口
    \f
    :param user:
    :param db:
    :return:
    """
    db_user = crud.get_user_by_eamil(db, email=user.email, query_time=datetime.now())
    if db_user:
        raise HTTPException(status_code=400, detail='email already registered')
    return crud.create_user(db=db, user=user)


@router.get('/', response_model=List[schemas.User], tags=['users'])
def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    users = crud.get_users(db, skip=skip, limit=limit)
    return users


@router.get('/email', response_model=List[schemas.User], tags=['users'])
def read_user_by_email(email: str = None, update_time: datetime = None, db: Session = Depends(get_db)):
    # 获取更改时间超过一天的/通过email模糊查询
    users = crud.get_user_by_eamil(db, email, update_time)
    return users


@router.put('/update', response_model=List[schemas.User], tags=['users'])
def batch_update_user_info(update_time: datetime = None, db: Session = Depends(get_db)):
    # 根据修改时间,批量更新(类似将手动取消的域名状态全部设置成可用)
    users = crud.batch_update_user(db, update_time)
    return users


@router.get('/{user_id}', response_model=schemas.User, tags=['users'])
def read_users(user_id: int, db: Session = Depends(get_db)):
    logger.debug('user一个debug信息')
    logger.info('user一个info信息')
    logger.war('user一个warning信息')
    logger.error('user一个error信息')
    logger.cri('user一个致命critical信息')
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail='User not found')
    return db_user


@router.put('/{user_id}', tags=['users'])
def update_users(user_id: int, email: str = Body(...), password: str = Body(None), db: Session = Depends(get_db)):
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail='User not found')
    db_user = crud.update_user(db, user_id=user_id, email=email, password=password)
    return db_user


@router.delete('/{user_id}', tags=['users'])
def delete_users(user_id: int, db: Session = Depends(get_db)):
    db_user = crud.get_user(db, user_id=user_id)
    if db_user is None:
        raise HTTPException(status_code=404, detail='User not found')
    db_user = crud.delete_user(db, user_id=user_id)
    return db_user
schemas.py (接口调用传参、返回的模型)
from pydantic import BaseModel, Json
from typing import List


class ItemBase(BaseModel):
    title: str
    description: str = None


class ItemCreate(ItemBase):
    pass


class Item(ItemBase):
    id: int
    owner_id: int

    class Config:   # https://pydantic-docs.helpmanual.io/usage/model_config/
        orm_mode = True   # 是否允许使用orm模式  没有orm_mode,如果您从路径操作返回了SQLAlchemy模型,则该模型将不包含关系数据。


class UserBase(BaseModel):
    email: str


class UserCreate(UserBase):
    password: str
    info: dict


class User(UserBase):
    id: int
    is_active: bool
    info: dict   # 字典就是json格式
    items: List[Item] = []

    class Config:
        orm_mode = True
### 关于FastAPI和Vue3的学习教程与笔记 #### 使用FastAPI构建后端服务 为了创建一个基于FastAPI的Web应用,开发者可以利用其简洁而强大的特性来快速搭建RESTful API。下面是一个简单的例子,展示了如何设置带有跨源资源共享(CORS)中间件的基础应用程序[^4]。 ```python from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() # 添加CORS中间件允许所有来源访问API app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"] ) @app.get("/") async def read_root(): return {"message": "Hello World"} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) ``` 这段代码定义了一个基本的应用实例`app`并配置了必要的中间件以支持来自不同域的请求。通过装饰器`@app.get("/")`指定了根路径处理程序返回一条消息给客户端。 #### 利用Vue3设计前端界面 对于前端部分,则推荐采用现代JavaScript框架之一——Vue.js版本3来进行单页面应用程序(SPA)的设计工作。这里给出一段HTML模板以及相应的脚本片段用于初始化一个新的Vue项目: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>My App</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app">{{ message }}</div> <!-- 创建Vue实例 --> <script type="module"> import { createApp } from 'vue' createApp({ data() { return { message: 'Welcome to your new Vue application!' }; } }).mount('#app') </script> </body> </html> ``` 此示例中引入了最新版的Vue库文件,并通过ES模块语法动态加载它;接着声明了一个名为`app`的对象作为视图模型(View Model),其中包含了要绑定到DOM中的属性(`message`)及其初始值;最后调用了`.mount()`方法指定挂载点从而启动整个SPA生命周期。 #### 结合FastAPI与Vue3的最佳实践建议 当考虑将这两个工具链结合起来时,有几个方面值得注意: - **前后端分离架构**:保持清晰的服务层划分有助于团队协作分工明确; - **状态管理解决方案的选择**:针对复杂的状态逻辑可以选择Vuex或其他类似的库; - **HTTP通信协议**:通常会选用Axios发起异步请求并与服务器交互获取资源; - **安全性考量**:确保传输过程加密(HTTPS)、身份验证机制健全等措施保障信息安全[^1]。 #### 实战经验分享 根据实际案例分析,在学习过程中采取边做边学的方式往往能取得更好的效果。比如可以从模仿现有优秀作品入手,逐步理解各个知识点之间的联系,再尝试独立完成小型项目积累更多实践经验。此外,积极参与社区讨论也是不可或缺的一环,这不仅能够帮助解决遇到的具体难题,更能拓宽视野接触到最新的行业趋势和技术动向[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值