mirror of
https://github.com/grillazz/fastapi-sqlalchemy-asyncpg.git
synced 2025-08-26 16:40:40 +03:00
Merge pull request #97 from grillazz/96-migrate-to-pydantic-2
96 migrate to pydantic 2
This commit is contained in:
commit
d9e88d8ffc
1
.env
1
.env
@ -6,6 +6,7 @@ SQL_TEST_DB=testdb
|
|||||||
SQL_HOST=db
|
SQL_HOST=db
|
||||||
SQL_USER=user
|
SQL_USER=user
|
||||||
SQL_PASS=secret
|
SQL_PASS=secret
|
||||||
|
SQL_URL=postgresql+asyncpg://${SQL_USER}:${SQL_PASS}@${SQL_HOST}/${SQL_DB}
|
||||||
|
|
||||||
ALGORITHM=HS256
|
ALGORITHM=HS256
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||||
|
3
.github/workflows/build-and-test.yml
vendored
3
.github/workflows/build-and-test.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [ "3.11" ]
|
python-version: [ "3.11" ]
|
||||||
poetry-version: [ "1.4.0" ]
|
poetry-version: [ "1.5.1" ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHONDONTWRITEBYTECODE: 1
|
PYTHONDONTWRITEBYTECODE: 1
|
||||||
@ -23,6 +23,7 @@ jobs:
|
|||||||
SQL_USER: app-user
|
SQL_USER: app-user
|
||||||
POSTGRES_PASSWORD: secret
|
POSTGRES_PASSWORD: secret
|
||||||
PGPASSWORD: secret
|
PGPASSWORD: secret
|
||||||
|
SQL_URL: postgresql+asyncpg://app-user:secret@localhost:5432/testdb
|
||||||
|
|
||||||
services:
|
services:
|
||||||
sqldb:
|
sqldb:
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Example of [FastAPI](https://fastapi.tiangolo.com/) integration supported by almighty [Pydantic](https://github.com/pydantic/pydantic)
|
Example of [FastAPI](https://fastapi.tiangolo.com/) integration supported by almighty [Pydantic 2.0](https://github.com/pydantic/pydantic)
|
||||||
with [SQLAlchemy ORM](https://www.sqlalchemy.org/) and PostgreSQL
|
with [SQLAlchemy ORM](https://www.sqlalchemy.org/) and PostgreSQL
|
||||||
connected via fastest Database Client Library for python/asyncio [asyncpg](https://github.com/MagicStack/asyncpg).
|
connected via fastest Database Client Library for python/asyncio [asyncpg](https://github.com/MagicStack/asyncpg).
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ Hope you enjoy it.
|
|||||||
- 14 FEB 2023 bump project to Python 3.11
|
- 14 FEB 2023 bump project to Python 3.11
|
||||||
- 10 APR 2023 implement logging with rich
|
- 10 APR 2023 implement logging with rich
|
||||||
- 28 APR 2023 Rainbow logs with rich :rainbow:
|
- 28 APR 2023 Rainbow logs with rich :rainbow:
|
||||||
|
- 7 JUL 2023 migrate to pydantic 2.0
|
||||||
|
|
||||||
### Local development with poetry
|
### Local development with poetry
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ async def update_nonsense(
|
|||||||
db_session: AsyncSession = Depends(get_db),
|
db_session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
nonsense = await Nonsense.find(db_session, name)
|
nonsense = await Nonsense.find(db_session, name)
|
||||||
await nonsense.update(db_session, **payload.dict())
|
await nonsense.update(db_session, **payload.model_dump())
|
||||||
return nonsense
|
return nonsense
|
||||||
|
|
||||||
|
|
||||||
@ -45,6 +45,6 @@ async def merge_nonsense(
|
|||||||
payload: NonsenseSchema,
|
payload: NonsenseSchema,
|
||||||
db_session: AsyncSession = Depends(get_db),
|
db_session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
nonsense = Nonsense(**payload.dict())
|
nonsense = Nonsense(**payload.model_dump())
|
||||||
await nonsense.save_or_update(db_session)
|
await nonsense.save_or_update(db_session)
|
||||||
return nonsense
|
return nonsense
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Query
|
from fastapi import APIRouter, Depends, Query
|
||||||
from pydantic import Required
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from app.database import get_db
|
from app.database import get_db
|
||||||
@ -14,7 +13,7 @@ router = APIRouter(prefix="/v1/shakespeare")
|
|||||||
"/",
|
"/",
|
||||||
)
|
)
|
||||||
async def find_paragraph(
|
async def find_paragraph(
|
||||||
character: Annotated[str, Query(description="Character name")] = Required,
|
character: Annotated[str, Query(description="Character name")],
|
||||||
db_session: AsyncSession = Depends(get_db),
|
db_session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
return await Paragraph.find(db_session=db_session, character=character)
|
return await Paragraph.find(db_session=db_session, character=character)
|
||||||
|
@ -54,5 +54,5 @@ async def update_stuff(
|
|||||||
db_session: AsyncSession = Depends(get_db),
|
db_session: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
stuff = await Stuff.find(db_session, name)
|
stuff = await Stuff.find(db_session, name)
|
||||||
await stuff.update(db_session, **payload.dict())
|
await stuff.update(db_session, **payload.model_dump())
|
||||||
return stuff
|
return stuff
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
from pydantic import BaseSettings, PostgresDsn
|
from pydantic import PostgresDsn
|
||||||
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
asyncpg_url: PostgresDsn = PostgresDsn.build(
|
asyncpg_url: PostgresDsn = os.getenv("SQL_URL")
|
||||||
scheme="postgresql+asyncpg",
|
|
||||||
user=os.getenv("SQL_USER"),
|
|
||||||
password=os.getenv("POSTGRES_PASSWORD"),
|
|
||||||
host=os.getenv("SQL_HOST"),
|
|
||||||
port="5432",
|
|
||||||
path=f"/{os.getenv('SQL_DB') or ''}",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@lru_cache
|
@lru_cache
|
||||||
|
@ -10,7 +10,7 @@ global_settings = config.get_settings()
|
|||||||
logger = AppLogger.__call__().get_logger()
|
logger = AppLogger.__call__().get_logger()
|
||||||
|
|
||||||
engine = create_async_engine(
|
engine = create_async_engine(
|
||||||
global_settings.asyncpg_url,
|
global_settings.asyncpg_url.unicode_string(),
|
||||||
future=True,
|
future=True,
|
||||||
echo=True,
|
echo=True,
|
||||||
)
|
)
|
||||||
|
@ -14,8 +14,8 @@ class NonsenseSchema(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
from_attributes = True
|
||||||
schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"name": "Name for Some Nonsense",
|
"name": "Name for Some Nonsense",
|
||||||
"description": "Some Nonsense Description",
|
"description": "Some Nonsense Description",
|
||||||
@ -38,8 +38,8 @@ class NonsenseResponse(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
from_attributes = True
|
||||||
schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"config_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
"config_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
"name": "Name for Some Nonsense",
|
"name": "Name for Some Nonsense",
|
||||||
|
@ -14,8 +14,8 @@ class StuffSchema(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
from_attributes = True
|
||||||
schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"name": "Name for Some Stuff",
|
"name": "Name for Some Stuff",
|
||||||
"description": "Some Stuff Description",
|
"description": "Some Stuff Description",
|
||||||
@ -38,8 +38,8 @@ class StuffResponse(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
from_attributes = True
|
||||||
schema_extra = {
|
json_schema_extra = {
|
||||||
"example": {
|
"example": {
|
||||||
"config_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
"config_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
||||||
"name": "Name for Some Stuff",
|
"name": "Name for Some Stuff",
|
||||||
|
628
poetry.lock
generated
628
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "fastapi-sqlalchemy-asyncpg"
|
name = "fastapi-sqlalchemy-asyncpg"
|
||||||
version = "0.0.4"
|
version = "0.0.5"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Jakub Miazek <the@grillazz.com>"]
|
authors = ["Jakub Miazek <the@grillazz.com>"]
|
||||||
packages = []
|
packages = []
|
||||||
@ -26,6 +26,7 @@ ipython = "*"
|
|||||||
pytest-cov = "*"
|
pytest-cov = "*"
|
||||||
pytest-asyncio = "*"
|
pytest-asyncio = "*"
|
||||||
ruff = "*"
|
ruff = "*"
|
||||||
|
pydantic-settings = "^2.0.1"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
tryceratops = "^1.1.0"
|
tryceratops = "^1.1.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user