一、创建 model.py
from tortoise.models import Model class Tournament(Model): id = fields.IntField(pk=True) name = fields.TextField() created = fields.DatetimeField(auto_now_add=True) def __str__(self): return self.name class Event(Model): id = fields.IntField(pk=True) name = fields.TextField() tournament = fields.ForeignKeyField('models.Tournament', related_name='events') participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team') modified = fields.DatetimeField(auto_now=True) prize = fields.DecimalField(max_digits=10, decimal_places=2, null=True) def __str__(self): return self.name class Team(Model): id = fields.IntField(pk=True) name = fields.TextField() class Meta: abstract = True # 设置为True表明这是一个抽象类 table = "team" # 设置表名 table_description = "" # 设置此项可为为当前模型创建的表生成注释消息 unique_together = () # 指定unique_together为列集设置复合唯一索引,其为元组的元组(列表很好) indexes = () # 指定indexes为列集设置复合非唯一索引,它应该是元组的元组(列表很好) ordering = [] # 指定ordering为给定模型设置默认排序。.order_by(...)它应该可以迭代以与接收相同的方式格式化的字符串。如果查询是GROUP_BY使用默认排序的子句构建的,.annotate(...)则不应用。 manager = tortoise.manager.Manager # 指定manager覆盖默认管理器。它应该是实例tortoise.manager.Manager或子类。
2、 多表关联
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"] def __str__(self): return self.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" ) def __str__(self): return self.name class Team(Model): id = fields.IntField(pk=True) name = fields.CharField(max_length=255) events: fields.ManyToManyRelation[Event] def __str__(self): return self.name
3、字段 3.1 数据字段 Field(source_field = None , generated = False , pk = False , null = False , default = None , unique = False , index = False , description = None , model = None , validators = None , ** kwargs
参数: source_field (Optional[str]) : 如果 DB 列名称需要是特定的而不是从字段名称中生成,则提供 source_field 名称。 generated (bool) : 该字段是否由数据库生成 pk (bool) :该字段是否为主键 null (bool) :主键是否可以为空 default (Optional[Any]):该字段的默认值 unique (bool) :该字段的值是否唯一 index (bool):设置该字段是否为索引 description (Optional[str]) :字段描述,也将出现在Tortoise.describe_model() 生成的 DDL 中并作为 DB 注释出现。 validators (Optional[List[Union[Validator, Callable]]]) :此字段的验证器
3.2 关系字段 ForeignKeyField( model_name , related_name = None , on_delete = 'CASCADE' , db_constraint = True , ** kwargs )
参数: model_name:关联模型的名称{app}.{models} related_name:相关模型上的属性名称,用于反向解析外键 on_delete: field.CASCADE:表示如果相关模型被删除,该模型应该被级联删除 field.RESTRICT:表示只要有外键指向,相关模型删除就会受到限制 field.SET_NULL:将字段重置为 NULL,以防相关模型被删除。仅当字段已设置时才能null=True设置 field.SET_DEFAULT:将字段重置为default值,以防相关模型被删除。只能设置是字段有一个default集合 to_field:建立外键关系的相关模型上的属性名。如果未设置,则使用 pk db_constraint: 控制是否应在数据库中为此外键创建约束。默认值为 True,这几乎可以肯定是您想要的;将此设置为 False 可能对数据完整性非常不利
ManyToManyField(model_name, through=None, forward_key=None, backward_key='', related_name='', on_delete='CASCADE', db_constraint=True, **kwargs)
参数: through:通过中间表进行连接 forward_key: 直通表上的正向查找键。默认值通常是安全的 backward_key: 通表上的向后查找键。默认值通常是安全的
OneToOneField( model_name , related_name = None , on_delete = 'CASCADE' , db_constraint = True , ** kwargs )
4、 查询 4.1 基础 模型本身有几种方法可以启动查询:
filter(*args, **kwargs):使用给定的过滤器创建 QuerySet
exclude(*args, **kwargs):使用给定的排除过滤器创建 QuerySet
all():创建不带过滤器的查询集
first():创建仅限于一个对象的查询集并返回实例而不是列表
annotate(): 使用额外的函数/聚合对结果进行再过滤
此方法返回QuerySet对象,允许进一步过滤和一些更复杂的操作
模型类也有这个方法来创建对象:
create(**kwargs):使用给定的 kwargs 创建对象 get_or_create(defaults, **kwargs):获取给定 kwargs 的对象,如果未找到,则使用默认字典中的其他 kwargs 创建它 模型本身的实例也有这些方法:
save():更新实例,或者插入它,如果它以前从未保存过 delete():从数据库中删除实例 fetch_related(*args):获取与实例相关的对象。它可以获取 key关系、backward-key 关系。
values() # 返回queryset里面字段的值 values_list() # 返回queryset里面字段的值,同时,内部可以指定需要返回的字段的值 events = await Event.filter(id__in=[1,2,3]).values('id', 'name', tournament_name='tournament__name') 使用values()或values_list()生成更有效的查询
filter可以指定的对象:
not in:检查字段的值是否在传递列表中 not_in gte:大于或等于传递的值 gt:大于传递值 lte:低于或等于传递的值 lt:低于通过值 range:介于和给定两个值之间 isnull:字段为空 not_isnull:字段不为空 contains:字段包含指定的子字符串 icontains:不区分大小写contains startswith:如果字段以值开头 istartswith:不区分大小写startswith endswith:如果字段以值结尾 iendswith:不区分大小写endswith iexact:不区分大小写等于 search:全文搜索
使用示例: from tortoise.functions import Count, Trim, Lower, Upper, Coalesce # This query will fetch all tournaments with 10 or more events, and will # populate filed `.events_count` on instances with corresponding value await Tournament.annotate(events_count=Count('events')).filter(events_count__gte=10) await Tournament.annotate(clean_name=Trim('name')).filter(clean_name='tournament') await Tournament.annotate(name_upper=Upper('name')).filter(name_upper='TOURNAMENT') await Tournament.annotate(name_lower=Lower('name')).filter(name_lower='tournament') await Tournament.annotate(desc_clean=Coalesce('desc', '')).filter(desc_clean='')
4.2 Q 对象 Q 对象非常通用,一些示例用例:
创建 OR 过滤器 嵌套过滤器 倒置过滤器 结合以上任何一种来简单地编写复杂的多层过滤器 比如:
Q( * args , join_type = 'AND' , ** kwargs )
参数: join_type:连接类型,OR\AND args ( Q) :Q要包装的内部表达式 kwargs ( Any) :此 Q 对象应封装的过滤语句 found_events = await Event.filter( Q(Q(name='Event 1'), Q(name='Event 2'), join_type="OR") # Q(name='Event 1') | Q(name='Event 2')
4.3 F 表达式 F对象表示模型字段的值。它可以引用模型字段值并使用它们执行数据库操作,而无需将它们从数据库中拉出到 Python 内存中
from tortoise.expressions import F await User.filter(id=1).update(balance = F('balance') - 10) await User.filter(id=1).update(balance = F('balance') + F('award'), award = 0) # or use .save() user = await User.get(id=1) user.balance = F('balance') - 10 await user.save(update_fields=['balance'])
本文作者:赵耀伟
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!