You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI+Psycopg2关联查询返回嵌套JSON问题求助

FastAPI + Psycopg2 关联查询返回嵌套结构解决方案

1. 不使用ORM能否有效解决?

可以。核心是手动处理数据库查询结果的结构,将用户字段封装到owner嵌套对象中,再结合FastAPI的Pydantic模型完成序列化。

2. Psycopg2是否可以搭配ORM使用?

完全可以。比如常用的SQLAlchemy ORM就支持以Psycopg2(或psycopg2-binary)作为PostgreSQL的底层驱动,只需在SQLAlchemy的连接URL中指定即可:

from sqlalchemy import create_engine
engine = create_engine("postgresql://user:password@localhost/dbname?driver=psycopg2")

3. 实现期望返回格式的具体步骤

步骤1:优化SQL查询语句

避免使用SELECT *,明确指定字段并给重复字段(如id)起别名,防止字段冲突:

SELECT 
    posts.id AS post_id, posts.title, posts.content, posts.published, 
    posts.created_at AS post_created_at, posts.user_id,
    users.id AS owner_id, users.email, users.created_at AS owner_created_at
FROM posts
JOIN users ON users.id = posts.user_id

步骤2:用DictCursor处理结果并构建嵌套结构

使用Psycopg2的DictCursor让查询结果以字典形式返回,更方便字段映射。先配置游标:

import psycopg2.extras
curr = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

然后修改接口函数,手动拆分字段组装成符合模型的结构:

@router.get("/", response_model=list[sh.PostResponse])
def get_posts():  # 修正原代码笔误:ger_posts → get_posts
    curr.execute("""
        SELECT 
            posts.id AS post_id, posts.title, posts.content, posts.published, 
            posts.created_at AS post_created_at, posts.user_id,
            users.id AS owner_id, users.email, users.created_at AS owner_created_at
        FROM posts
        JOIN users ON users.id = posts.user_id
    """)
    posts = curr.fetchall()
    
    result = []
    for post in posts:
        # 组装owner嵌套对象
        owner_data = {
            "id": post["owner_id"],
            "email": post["email"],
            "created_at": post["owner_created_at"]
        }
        # 组装post主对象
        post_data = {
            "id": post["post_id"],
            "title": post["title"],
            "content": post["content"],
            "published": post["published"],
            "created_at": post["post_created_at"],
            "user_id": post["user_id"],
            "owner": owner_data
        }
        result.append(post_data)
    
    # 查询操作无需commit,移除原代码中的conn.commit()
    return result

步骤3:确认Pydantic模型正确性

你的模型定义已经符合要求,只要传入的数据结构匹配,FastAPI会自动完成JSON序列化:

from pydantic import BaseModel, EmailStr
from datetime import datetime

class UserResponse(BaseModel):
    id: int
    email: EmailStr
    created_at: datetime  

class PostBase(BaseModel):
    title: str
    content: str
    published: bool = True

class PostResponse(PostBase):
    id: int
    created_at: datetime
    user_id: int
    owner: UserResponse

内容的提问来源于stack exchange,提问作者Lazare Janiashvili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:22:37