So called generics , Is to pass the data type as a parameter , That is, to determine the data type when we use it , This is a feature often used in object-oriented languages
With SQLAlchemy give an example
such as : We uniformly write an interface to save data to the database , Only will Database link
Table object
data
Just pass it in , The return is Instances of table objects
, In order to make IDE You can identify the return object , We can use generics
I need to use :
typing
Of TypeVar
and Type
TypeVar
Is a type variable , It is mainly used for parameters of generic types and generic function definitions , The first parameter is the name , bound
Parameter is used to specify that the type is bound
Subclass of value Type[C]
Is in the form of a covariate , indicate C
All subclasses of should Use And C
same Constructor signature And Class method signature , If we need to return generic types , Need to use
More ways to use , see : typing Use
Used pydantic
Specify the type of data to create
About
pydantic
General use of , see : Pydantic Use
from typing import TypeVar, Type
from sqlalchemy.orm import Session
from pydantic import BaseModel
from orm.models import Category
from orm.schemas import WriteCategoryModel
# Definition type
ModelT = TypeVar("ModelT")
DataT = TypeVar("DataT", bound=BaseModel) # bound Indicates that this class is BaseModel Subclasses of
"""
To save space , Table structures and models are not shown
"""
def create_category(session: Session, data: WriteCategoryModel) -> Type[Category]:
cate_obj = save_one_to_db(session=session, model_class=Category, data=data)
return cate_obj
def save_one_to_db(session: Session, model_class: ModelT, data: DataT) -> ModelT:
"""
Save a message to the database
:param session: SQLAlchemy Session
:param model_class: sqlalchemy Model class
:param data: pydantic Model object
:return: Corresponding sqlalchemy Object of model class
"""
try:
obj = model_class(**data.dict())
session.add(obj)
session.commit()
# Manual will data Refresh to database
session.refresh(obj)
return obj
except Exception as e:
# Don't forget to roll back when an error occurs
session.rollback()
raise e
In the use of pydantic when , You can also use generics
such as : stay FastAPI
The unified return format returned in is :
{
"status": true,
"msg": "success",
"data": ...
}
our data
It could be a list or an object , And the corresponding pydantic
The model is different , Then we can use generics
Code :
from typing import List, Optional, Generic, TypeVar
from fastapi import APIRouter, status, HTTPException
from pydantic import BaseModel
from pydantic.generics import GenericModel
router = APIRouter(prefix="/test", tags=[" Test generics "])
# For convenience , Defined here pydantic Model
DataT = TypeVar("DataT")
class GenericResponse(GenericModel, Generic[DataT]):
"""
General return data
"""
status: bool
msg: str
data: Optional[DataT] = None # May even data None
# Set up response_model_exclude_unset=True that will do
class BookModel(BaseModel):
id: int
name: str
# Pseudo data
fake_book_data = [
{"id": 1, "name": "book1"},
{"id": 2, "name": "book2"},
{"id": 3, "name": "book3"},
{"id": 4, "name": "book4"},
{"id": 5, "name": "book5"},
]
@router.get("/books", response_model=GenericResponse[List[BookModel]])
def get_books():
return {
"status": True,
"msg": " To be successful ",
"data": fake_book_data
}
@router.get("/books/{bid}", response_model=GenericResponse[BookModel])
def retrieve_book(bid: int):
for item in fake_book_data:
if item.get("id") == bid:
return {
"status": True,
"msg": " To be successful ",
"data": item
}
# non-existent
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=" The book does not exist ")
visit /docs
page , Successfully passed the test