因为源码有点长,这里只截取重要部分
from peewee import *
from peewee import Alias
import peewee_async
from Main.settings import database
objects = peewee_async.Manager(database)
database.set_allow_sync(False) # 异步化
_clone_set = lambda s: set(s) if s else set()
async def async_model_to_dict(model, recurse=True, backrefs=False, only=None,
exclude=None, seen=None, extra_attrs=None,
fields_from_query=None, max_depth=None):
max_depth = -1 if max_depth is None else max_depth
if max_depth == 0:
recurse = False
only = _clone_set(only)
extra_attrs = _clone_set(extra_attrs)
if fields_from_query is not None:
for item in fields_from_query._returning:
if isinstance(item, Field):
only.add(item)
elif isinstance(item, Alias):
extra_attrs.add(item._alias)
data = {}
exclude = _clone_set(exclude) # 记录所有外键
seen = _clone_set(seen)
exclude |= seen
model_class = type(model)
###########################################
此for循环取数据
for field in model._meta.sorted_fields:
if field in exclude or (only and (field not in only)):
continue
field_data = model.__data__.get(field.name)
if isinstance(field, ForeignKeyField) and recurse:
if field_data:
seen.add(field)
################################################
修改:异步化之后因为关联查询问题,field.name虽然有,但是取不到
这里直接return data的原因是这里只取一层外键,不再往上取二层
try:
rel_obj = getattr(model, field.name)
except:
return data
field_data = await async_model_to_dict(
rel_obj,
recurse=recurse,
backrefs=backrefs,
only=only,
exclude=exclude,
seen=seen,
max_depth=max_depth - 1)
else:
field_data = None
data[field.name] = field_data
#################################
这里是递归反向查询
if backrefs and recurse:
for foreign_key, rel_model in model._meta.backrefs.items():
if foreign_key.backref == '+': continue
descriptor = getattr(model_class, foreign_key.backref)
if descriptor in exclude or foreign_key in exclude:
continue
if only and (descriptor not in only) and (foreign_key not in only):
continue
accum = []
exclude.add(foreign_key)
related_query = getattr(model, foreign_key.backref)
try:
#########################################
为什么这里从原来的 for rel_obj in related_query:
加上了 objects.execute,因为同步的模式使用for循环就可以
使query对象执行,而异步的模式会出错,因此要手动execute
related_objects = await objects.execute(related_query)
for rel_obj in related_objects:
accum.append(await async_model_to_dict(
rel_obj,
recurse=recurse,
backrefs=backrefs,
only=only,
exclude=exclude,
max_depth=max_depth - 1))
data[foreign_key.backref] = accum
except AssertionError:
recurse = False
return data
网友评论