https://github.com/allmonday/pydantic-resolve-demo
a pydantic-resolve demo based on FastAPI
https://github.com/allmonday/pydantic-resolve-demo
fastapi graphql pydantic pydantic-resolve
Last synced: 11 months ago
JSON representation
a pydantic-resolve demo based on FastAPI
- Host: GitHub
- URL: https://github.com/allmonday/pydantic-resolve-demo
- Owner: allmonday
- Created: 2024-07-24T14:11:16.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-05-03T11:56:34.000Z (about 1 year ago)
- Last Synced: 2025-05-03T12:33:13.472Z (about 1 year ago)
- Topics: fastapi, graphql, pydantic, pydantic-resolve
- Language: TypeScript
- Homepage: https://allmonday.github.io/pydantic-resolve/
- Size: 891 KB
- Stars: 8
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# pydantic-resolve-demo
For FastAPI user, we already have pydantic, openapi support and openapi-ts, pydantic-resolve is the last puzzle for a better development pattern.
pydantic-resolve: https://github.com/allmonday/pydantic-resolve
This repo shows how to define and compose schemas together with pydantic-resolve, and also sync schemas and methods to frontend with openapi-ts.
Based on the business model, there are three basic entities: Blog, Comment, User
after that, we can easily build new complicated model by inheriting and extending
- sample 1: show blogs
- sample 2: show blogs with comments
- sample 3: show author info of comments
from 1 to 3, you will progressively add more and more fields into the response model, and the client side can sense it immediately.

```python
class MyBlogSite(BaseModel):
name: str
# blogs: list[Blog] = [] # this will not include comments and comment_count
blogs: list[MyBlog] = []
async def resolve_blogs(self):
return await get_blogs()
comment_count: int = 0
def post_comment_count(self):
return sum([b.comment_count for b in self.blogs])
class MyBlog(Blog):
# comments: list[Comment] = [] # this will not include user field
comments: list[MyComment] = []
def resolve_comments(self, loader=LoaderDepend(blog_to_comments_loader)):
return loader.load(self.id)
comment_count: int = 0
def post_comment_count(self):
return len(self.comments)
class MyComment(Comment):
user: Optional[User] = None
def resolve_user(self, loader=LoaderDepend(user_loader)):
return loader.load(self.user_id)
```
We only need to make sure the return value from `resolve_blogs` or `resolve_comments` can be converted to BASE schemas (Blog, Comment)
then we can replace `blogs: list[Blog] = []` to `blogs: list[MyBlog] = []` to extend more fields.
## BE
prefer python >= 3.10
```shell
python -m venv venv
source venv/bin/activate
pip install -r requirement.pip
fastapi dev main.py
```
```python
@app.get("/my-site/{name}", response_model=MyBlogSite, tags=["main"])
async def read_my_site(name: str):
site = MyBlogSite(name=name)
return await Resolver().resolve(site)
```
visit http://localhost:8000/docs#/main/read_my_site
## FE
ensure server is running, and then generate the client from `localhost:8000/openapi.json`
```shell
cd fe
npm install
npm run openapi-ts
npx ts-node main.ts
```
```ts
import { MainService } from './src/client'
// whti this can avoid the impact of renaming schema name
type AsyncReturnType any> = Awaited>;
type ReadMySite1 = typeof ModuleAService.readMySite1;
type MySite1 = AsyncReturnType;
type Param1 = Parameters[0];
(async () => {
const name: Param['name'] = 'tangkikodo'
const data: MySite = await MainService.readMySite({ name: name })
console.log(JSON.stringify(data, null, 2))
})()
```
inspect the log output