祥开龙角应三农,小队旌旗猎猎风。
models.py
class Group (Model ):
id = IntField(pk=True )
name = CharField(max_length=10 )
class User (Model ):
id = IntField(pk=True )
group = ForeignKeyField('models.Group' )
name = CharField(max_length=10 )
utils.py
async def get_user_data (group_id: int , user_data: list [dict ] ) -> list [dict ]:
return [dict (i, group=group_id) for i in user_data]
views.py
@router.get('' )
async def user_pages (params: Params = Depends( ), group_id: str = None ):
user_data = await User.all ().prefetch_related('group' )
user_list = await get_user_data(group_id=group_id, user_data=user_data)
data = paginate(user_list, params=params)
return Response(status=0 , data=data)
修改后的views.py
from fastapi_pagination.ext.tortoise import paginate
@router.get('' )
async def user_pages (params: Params = Depends( ), group_id: str = None ):
queryset = User.all ().prefetch_related('group' )
async def transformer (items ):
return await get_user_data(group_id=group_id, user_data=items)
data = await paginate(
queryset, params=params, transformer=transformer
)
return MyResponse(status=0 , data=data)
示例2:(能修改get_user_data方法的情况)
import functools
async def get_user_data (user_data: list [dict ], group_id, **kw ) -> list [dict ]:
return [dict (i, group_id=group_id) for i in user_data]
@router.get('' )
async def user_pages (params: Params = Depends( ), group_id: str = None ):
queryset = User.all ().prefetch_related('group' )
transformer = functools.partial(get_user_data, group_id=group_id)
data = await paginate(
queryset, params=params, transformer=transformer
)
return MyResponse(status=0 , data=data)
一个完整的示例:
from contextlib import asynccontextmanager
from functools import partial
from pathlib import Path
from typing import (
TYPE_CHECKING,
Annotated,
Any ,
AsyncGenerator,
Optional ,
)
import fastapi_cdn_host
import uvicorn
from faker import Faker
from fastapi import Depends, FastAPI
from fastapi_pagination import LimitOffsetPage, Page, Params, add_pagination
from fastapi_pagination.ext.tortoise import paginate
from pydantic import BaseModel, Field
from tortoise import fields, models
from tortoise.contrib.fastapi import RegisterTortoise
from tortoise.contrib.pydantic import PydanticModel, pydantic_model_creator
from tortoise.exceptions import DoesNotExist
faker = Faker()
class Group (models.Model):
id = fields.IntField(pk=True )
name = fields.TextField()
users: fields.ReverseRelation["User" ]
class User (models.Model):
id = fields.IntField(pk=True )
name = fields.TextField(null=False )
email = fields.TextField(null=False )
group: fields.ForeignKeyRelation[Group] = fields.ForeignKeyField(
"models.Group" , related_name="users"
)
if TYPE_CHECKING:
class UserIn (User, PydanticModel):
pass
class UserOut (User, PydanticModel):
pass
else :
UserOut = pydantic_model_creator(User, name="User" )
class UserIn (pydantic_model_creator(User, name="UserIn" , exclude_readonly=True )):
group_id: int = Field(gt=0 )
async def _initial_users () -> None :
await Group.bulk_create([Group(name=faker.name()) for _ in range (10 )])
gs = await Group.all ()
for i in range (100 ):
await User.create(
name=faker.name(),
email=faker.email(),
group=gs[i % len (gs)],
)
class UserInfoSchema (BaseModel ):
user_id: int
info: Annotated[str , "<name email>" ]
group: str
async def build_user_info (items: list [UserOut], group_name="" ) -> list [UserInfoSchema]:
return [
UserInfoSchema(
user_id=i.id , info=f"<{i.name} {i.email} >" , group=group_name or i.group.name
)
for i in items
]
async def get_user_data (group_id, items ) -> list [UserInfoSchema]:
try :
g = await Group.get(id =group_id)
group_name = g.name
except (DoesNotExist, TypeError, ValueError):
group_name = ""
return await build_user_info(items, group_name)
@asynccontextmanager
async def lifespan (app: FastAPI ) -> AsyncGenerator[None , None ]:
async with RegisterTortoise(
app,
db_url="sqlite://:memory:" ,
modules={"models" : [__name__]},
generate_schemas=True ,
):
await _initial_users()
add_pagination(app)
yield
app = FastAPI(title="Tortoise ORM Pagination example" , lifespan=lifespan)
fastapi_cdn_host.patch_docs(app)
@app.post("/users" , response_model=UserOut )
async def create_user (user_in: UserIn ) -> Any :
return await User.create(**user_in.dict ())
@app.get("/users/default" , response_model=Page[UserInfoSchema] )
@app.get("/users/limit-offset" , response_model=LimitOffsetPage[UserInfoSchema] )
async def get_users () -> Any :
data = await paginate(
User.all ().prefetch_related("group" ),
transformer=partial(build_user_info, group_name="" ),
)
return data
class ResponseModel (BaseModel ):
status: int
data: Page[UserInfoSchema]
msg: Optional [str ] = ""
async def build_user_data (
user_data: list [UserOut], group_id: Optional [str ] = None
) -> list [UserInfoSchema]:
return await get_user_data(group_id=group_id, items=user_data)
@app.get("/users/info" , response_model=ResponseModel, summary="分页用户列表" )
async def get_user_infos (
params: Params = Depends( ), group_id: Optional [str ] = None
) -> Any :
queryset = User.all ().prefetch_related("group" )
if group_id:
queryset = queryset.filter (group_id=group_id)
transformer = partial(build_user_data, group_id=group_id)
data = await paginate(queryset, params=params, transformer=transformer)
return ResponseModel(status=0 , data=data)
class MyResponse :
def __init__ (self, data: Any , status: int , msg="" ) -> None :
self.data = data
self.status = status
if msg:
self.msg = msg
def __str__ (self ):
return {"data" : self.data, "status" : self.status}
@app.get("/users/info2" )
async def get_user_infos2 (params: Params = Depends( ), group_id: str = None ):
queryset = User.all ().prefetch_related("group" )
async def transformer (user_data ):
return await get_user_data(group_id=group_id, items=user_data)
data = await paginate(queryset, params=params, transformer=transformer)
return MyResponse(status=0 , data=data, msg="bibi" )
if __name__ == "__main__" :
uvicorn.run(f"{Path(__file__).stem} :app" )
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现