基于 FastAPI + Tortoise ORM 的企业信息管理后端实现
1. 引言在企业级应用开发中企业信息管理是常见的核心模块。本文将基于 FastAPI 异步框架和 Tortoise ORM详细解析一个完整的企业信息管理后端实现涵盖分页查询、关联数据获取、审核流程等关键功能。2. 技术栈与环境准备2.1 主要技术栈FastAPI: 现代、快速的 Web 框架支持异步编程Tortoise ORM: 异步 ORM支持 Django 风格的查询语法Pydantic: 数据验证和设置管理Python 3.8: 支持异步/await 语法2.2 模型定义示例在实现业务逻辑前需要先定义数据模型fromtortoiseimportfields,modelsfromenumimportIntEnumclassAccountStatus(IntEnum):PENDING0NORMAL1REJECTED2classAuthType(IntEnum):ENTERPRISE_LICENSE_AUTH1ID_CARD_AUTH2classEnterprise(models.Model):idfields.IntField(pkTrue)enterprise_namefields.CharField(max_length255)submit_timefields.DatetimeField(auto_now_addTrue)account_statusfields.IntEnumField(AccountStatus,defaultAccountStatus.PENDING)auth_timefields.DatetimeField(nullTrue)auth_typefields.IntEnumField(AuthType,nullTrue)classEnterpriseInfo(models.Model):enterprisefields.OneToOneField(models.Enterprise,related_nameinfo)industryfields.ForeignKeyField(models.Industry,related_nameenterprises,nullTrue)classEnterpriseQualification(models.Model):enterprisefields.OneToOneField(models.Enterprise,related_namequalification)contact_phonefields.CharField(max_length20)classEnterpriseReview(models.Model):enterprisefields.OneToOneField(models.Enterprise,related_namereview)review_resultfields.IntField()# 1: 通过, 0: 拒绝review_reasonfields.TextField(nullTrue)remarkfields.TextField(nullTrue)audit_timefields.DatetimeField(auto_nowTrue)3. 核心业务逻辑实现3.1 企业列表分页查询importmathimportloggingfromtypingimportOptional,Dict,Any loggerlogging.getLogger(__name__)classEnterpriseService:staticmethodasyncdefselect_enterprise_list(page:int,page_size:int,enterprise_name:strNone,submit_time_start:strNone,submit_time_end:strNone)-Dict[str,Any]: 分页查询企业列表支持名称模糊搜索和时间范围筛选 参数: page: 页码从1开始 page_size: 每页数量 enterprise_name: 企业名称模糊匹配 submit_time_start: 提交时间起始 submit_time_end: 提交时间截止 返回: 包含分页信息和企业详情的字典 # 构建基础查询query_enterpriseEnterprise.all()# 应用筛选条件ifenterprise_name:query_enterprisequery_enterprise.filter(enterprise_name__icontainsenterprise_name)ifsubmit_time_start:query_enterprisequery_enterprise.filter(submit_time__gtesubmit_time_start)ifsubmit_time_end:query_enterprisequery_enterprise.filter(submit_time__ltesubmit_time_end)# 计算分页信息total_countawaitquery_enterprise.count()total_pagemath.ceil(total_count/page_size)offset(page-1)*page_size# 执行分页查询query_enterpriseawaitquery_enterprise.offset(offset).limit(page_size)logger.info(fquery_enterprise:{query_enterprise})# 组装返回数据enterprise_list[]forenterpriseinquery_enterprise:enterprise_identerprise.id# 关联查询企业信息和资质enterpriseinfoawaitEnterpriseInfo.get_or_none(enterprise_identerprise_id).prefetch_related(industry)enterprise_qualificationawaitEnterpriseQualification.get_or_none(enterprise_identerprise_id)# 构建返回对象res_dict{enterprise:enterprise,enterpriseinfo:enterpriseinfo,enterprise_qualification:enterprise_qualification,industry:enterpriseinfo.industry.nameifenterpriseinfoandenterpriseinfo.industryelseNone}enterprise_list.append(res_dict)return{total_count:total_count,total_page:total_page,page:page,page_size:page_size,enterprise_list:enterprise_list}实现要点解析链式查询: Tortoise ORM 支持 Django 风格的链式查询语法条件筛选: 使用filter()方法添加查询条件支持__icontains不区分大小写包含等查询操作符分页处理: 手动计算 offset 实现分页适合中小数据量场景关联查询: 使用prefetch_related()预加载关联对象避免 N1 查询问题3.2 企业详情查询staticmethodasyncdefselect_enterprise_by_id(enterprise_id:int)-Dict[str,Any]: 根据企业ID查询企业详情 参数: enterprise_id: 企业ID 返回: 包含企业、企业信息、资质和行业的字典 # 并行查询企业基本信息、企业信息和资质enterpriseawaitEnterprise.get_or_none(identerprise_id)enterpriseinfoawaitEnterpriseInfo.get_or_none(enterprise_identerprise_id).prefetch_related(industry)enterprise_qualificationawaitEnterpriseQualification.get_or_none(enterprise_identerprise_id)return{enterprise:enterprise,enterpriseinfo:enterpriseinfo,enterprise_qualification:enterprise_qualification,industry:enterpriseinfo.industry.nameifenterpriseinfoandenterpriseinfo.industryelseNone}实现要点解析并行查询: 三个await查询可以并行执行提高查询效率空值处理: 使用get_or_none()避免查询不存在的记录时抛出异常数据组装: 将多个关联对象组装成统一的返回结构3.3 企业审核流程fromdatetimeimportdatetimefrompydanticimportBaseModelfromtypingimportOptionalclassEnterpriseReviewCreateRequest(BaseModel):企业审核请求模型enterprise_id:intreview_result:int# 1: 通过, 0: 拒绝review_reason:Optional[str]Noneremark:Optional[str]Nonedefnow()-datetime:获取当前时间returndatetime.now()staticmethodasyncdefenterprise_review(enterpriseReviewCreateRequest:EnterpriseReviewCreateRequest): 处理企业审核 参数: enterpriseReviewCreateRequest: 审核请求对象 流程: 1. 检查是否已有审核记录 2. 创建或更新审核记录 3. 如果审核通过更新企业状态 enterprise_identerpriseReviewCreateRequest.enterprise_id# 查询现有审核记录enterprise_reviewawaitEnterpriseReview.get_or_none(enterprise_identerprise_id)ifenterprise_reviewisNone:# 创建新的审核记录awaitEnterpriseReview.create(enterprise_identerprise_id,review_resultenterpriseReviewCreateRequest.review_result,review_reasonenterpriseReviewCreateRequest.review_reason,remarkenterpriseReviewCreateRequest.remark,audit_timenow())else:# 更新现有审核记录enterprise_review.review_result(enterpriseReviewCreateRequest.review_resultifenterpriseReviewCreateRequest.review_resultelseenterprise_review.review_result)enterprise_review.review_reason(enterpriseReviewCreateRequest.review_reasonifenterpriseReviewCreateRequest.review_reasonelseenterprise_review.review_reason)enterprise_review.remark(enterpriseReviewCreateRequest.remarkifenterpriseReviewCreateRequest.remarkelseenterprise_review.remark)enterprise_review.audit_timenow()awaitenterprise_review.save()# 如果审核通过更新企业状态ifenterpriseReviewCreateRequest.review_result1:enterpriseawaitEnterprise.get_or_none(identerprise_id)enterprise.account_statusAccountStatus.NORMAL enterprise.auth_timenow()enterprise.auth_typeAuthType.ENTERPRISE_LICENSE_AUTHawaitenterprise.save()# TODO: 添加历史审核记录发送短信或邮件通知用户实现要点解析审核状态管理: 使用枚举类型管理审核状态提高代码可读性创建或更新: 使用get_or_none() 条件判断实现 upsert 操作条件更新: 只更新传入的非空字段保留原有值业务联动: 审核通过后自动更新企业状态和认证信息3.4 企业登录验证frompydanticimportBaseModelclassLoginMobileRequest(BaseModel):手机号登录请求模型mobile:strstaticmethodasyncdeflogin(loginMobileRequest:LoginMobileRequest): 企业用户手机号登录 参数: loginMobileRequest: 登录请求对象 返回: 企业信息或抛出异常 注意: 一个手机号可能对应多个企业资质 enterprise_qualificationsawaitEnterpriseQualification.filter(contact_phoneloginMobileRequest.mobile)ifnotenterprise_qualifications:raiseException(手机号不存在)# 遍历所有关联的企业forenterprise_qualificationinenterprise_qualifications:enterprise_identerprise_qualification.enterprise_id logger.info(fenterprise_id:{enterprise_id})# 查询企业审核状态enterprise_reviewawaitEnterpriseReview.get_or_none(enterprise_identerprise_id)logger.info(fenterprise_review:{enterprise_review})# TODO: 根据审核状态决定是否允许登录# 这里可以添加更多的登录逻辑# TODO: 返回登录结果如 JWT token 等4. API 接口封装4.1 FastAPI 路由定义fromfastapiimportAPIRouter,HTTPExceptionfromtypingimportOptional routerAPIRouter(prefix/enterprise,tags[企业管理])router.get(/list)asyncdefget_enterprise_list(page:int1,page_size:int10,enterprise_name:Optional[str]None,submit_time_start:Optional[str]None,submit_time_end:Optional[str]None):获取企业列表try:resultawaitEnterpriseService.select_enterprise_list(pagepage,page_sizepage_size,enterprise_nameenterprise_name,submit_time_startsubmit_time_start,submit_time_endsubmit_time_end)return{code:200,message:success,data:result}exceptExceptionase:raiseHTTPException(status_code500,detailstr(e))router.get(/{enterprise_id})asyncdefget_enterprise_detail(enterprise_id:int):获取企业详情try:resultawaitEnterpriseService.select_enterprise_by_id(enterprise_id)ifnotresult[enterprise]:raiseHTTPException(status_code404,detail企业不存在)return{code:200,message:success,data:result}exceptHTTPException:raiseexceptExceptionase:raiseHTTPException(status_code500,detailstr(e))router.post(/review)asyncdefreview_enterprise(request:EnterpriseReviewCreateRequest):审核企业try:awaitEnterpriseService.enterprise_review(request)return{code:200,message:审核成功}exceptExceptionase:raiseHTTPException(status_code500,detailstr(e))router.post(/login)asyncdefenterprise_login(request:LoginMobileRequest):企业登录try:awaitEnterpriseService.login(request)return{code:200,message:登录成功}exceptExceptionase:raiseHTTPException(status_code400,detailstr(e))5. 性能优化建议5.1 查询优化索引优化: 为频繁查询的字段添加数据库索引classEnterprise(models.Model):# 为企业名称和提交时间添加索引enterprise_namefields.CharField(max_length255,indexTrue)submit_timefields.DatetimeField(auto_now_addTrue,indexTrue)分页优化: 对于大数据量考虑使用游标分页关联查询: 使用select_related()和prefetch_related()减少查询次数5.2 代码优化异步批处理: 使用asyncio.gather()并行执行多个查询enterprise,enterpriseinfo,enterprise_qualificationawaitasyncio.gather(Enterprise.get_or_none(identerprise_id),EnterpriseInfo.get_or_none(enterprise_identerprise_id).prefetch_related(industry),EnterpriseQualification.get_or_none(enterprise_identerprise_id))缓存策略: 对不常变的数据添加 Redis 缓存6. 错误处理与日志6.1 自定义异常classEnterpriseException(Exception):企业相关异常基类passclassEnterpriseNotFound(EnterpriseException):企业不存在异常passclassReviewFailed(EnterpriseException):审核失败异常pass6.2 结构化日志importstructlog loggerstructlog.get_logger()# 在关键业务点添加日志logger.info(enterprise_query_completed,total_counttotal_count,pagepage,page_sizepage_size,filter_conditions{enterprise_name:enterprise_name,time_range:f{submit_time_start}to{submit_time_end}})7. 总结本文详细介绍了基于 FastAPI 和 Tortoise ORM 的企业信息管理后端实现涵盖了数据模型设计: 使用 Tortoise ORM 定义企业相关实体核心业务逻辑: 分页查询、详情获取、审核流程、登录验证API 接口封装: 使用 FastAPI 提供 RESTful 接口性能优化: 查询优化、异步处理、缓存策略错误处理: 自定义异常和结构化日志这套实现方案具有以下优点异步高性能: 充分利用 Python 异步特性代码清晰: 使用类型注解和 Pydantic 模型易于扩展: 模块化设计便于添加新功能生产就绪: 包含错误处理、日志记录等生产环境必备特性在实际项目中可以根据具体需求进一步扩展如添加权限控制、数据导出、统计分析等功能。