from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from models import User_Pydantic, UserIn_Pydantic, Users
from tortoise.contrib.fastapi import HTTPNotFoundError, register_tortoise
app = FastAPI(title="Tortoise ORM FastAPI example")
...
register_tortoise(#这里是启动app的,之后会考虑和使用uvicorn启动的性能差别
app,
db_url="sqlite://:memory:",#数据库信息
modules={"models": ["models"]},#models列表
generate_schemas=True,#如果数据库为空,则自动生成对应表单,生产环境不要开
add_exception_handlers=True,#生产环境不要开,会泄露调试信息
)
引入tortoise-orm的方法:register_tortoise 解释
def register_tortoise(
app: FastAPI,
config: Optional[dict] = None,
config_file: Optional[str] = None,
db_url: Optional[str] = None,
modules: Optional[Dict[str, List[str]]] = None,
generate_schemas: bool = False,
add_exception_handlers: bool = False,
) -> None:
"""
在fastapi注册startup和shutdown
使用 ``config``, ``config_file``或 ``(db_url, modules)``三者之一来配置
示例
----------
config:
Dict containing config:
Example
-------
{
'connections': {
# Dict format for connection
'default': {
'engine': 'tortoise.backends.asyncpg',
'credentials': {
'host': 'localhost',
'port': '5432',
'user': 'tortoise',
'password': 'qwerty123',
'database': 'test',
}
},
# Using a DB_URL string
'default': 'postgres://postgres:qwerty123@localhost:5432/events'
},
'apps': {
'models': {
'models': ['__main__'],
# If no default_connection specified, defaults to 'default'
'default_connection': 'default',
}
}
}
config_file:
Path to .json or .yml (if PyYAML installed) file containing config with
same format as above.
db_url:
Use a DB_URL string. See :ref:`db_url`
modules:
Dictionary of ``key``: [``list_of_modules``] that defined "apps" and modules that
should be discovered for models.
generate_schemas:
True立即生成模式。仅适用于开发环境或SQLite ' ':memory: ' '数据库,生产环境数据库一定手动生成。
add_exception_handlers:
为' ' DoesNotExist ' ' & ' ' IntegrityError ' '添加一些自动异常处理程序。
不建议用于生产系统,因为它可能会泄漏数据
"""
pass
创建对应数据模型
tortoise-orm能使用的数据类型还挺丰富,满足了日常使用的需求。
创建Model
from tortoise import fields
from tortoise.models import Model
class User(Model):
id=fields.IntField(pk=True)#主键必不可少
通过继承的方式创建Model
from tortoise import fields
from tortoise.models import Model
class TimestampMixin():
created_at = fields.DatetimeField(null=True, auto_now_add=True)
modified_at = fields.DatetimeField(null=True, auto_now=True)
class NameMixin():
name = fields.CharField(40, unique=True)
class MyAbstractBaseModel(Model):
id = fields.IntField(pk=True)
class Meta:
abstract = True
#注意数据库里面对应表顺序可能会比较乱。。
class UserModel(TimestampMixin, MyAbstractBaseModel):
# 覆盖继承的字段
id = fields.UUIDField(pk=True)
# 新增一些字段
first_name = fields.CharField(20, null=True)
class Meta:
table = "user"
class RoleModel(TimestampMixin, NameMixin, MyAbstractBaseModel):
class Meta:
table = "role"
from tortoise.models import Model
from tortoise import fields
class Tournament(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255)
events: fields.ReverseRelation["Event"]#仅用于代码提示,注意events必须和Event里面的外键指定的related_name同名
class Event(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255)
tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events"
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
)#注意多对多,两个model里面都要写,虽然复杂了点,但是有代码提示还是很合算的。。through在django里面是指定多对多表的名字和功能,需要手动创建,这里可能是示例代码不全吧。。得测试
class Team(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=255)
events: fields.ManyToManyRelation[Event]#反向关系,
class PydanticMeta:
"""
The ``PydanticMeta`` class is used to configure metadata for generating the pydantic Model.
Usage:
.. code-block:: python3
class Foo(Model):
...
class PydanticMeta:
exclude = ("foo", "baa")
computed = ("count_peanuts", )
"""
#: If not empty, only fields this property contains will be in the pydantic model
include: Tuple[str, ...] = ()
#: Fields listed in this property will be excluded from pydantic model
exclude: Tuple[str, ...] = ()
#: Computed fields can be listed here to use in pydantic model
computed: Tuple[str, ...] = ()
#: Use backward relations without annotations - not recommended, it can be huge data
#: without control
backward_relations: bool = True
#: Maximum recursion level allowed
max_recursion: int = 3
#: Allow cycles in recursion - This can result in HUGE data - Be careful!
#: Please use this with ``exclude``/``include`` and sane ``max_recursion``
allow_cycles: bool = False
#: If we should exclude raw fields (the ones have _id suffixes) of relations
exclude_raw_fields: bool = True
#: Sort fields alphabetically.
#: If not set (or ``False``) then leave fields in declaration order
sort_alphabetically: bool = False