美文网首页
async_model_to_dict

async_model_to_dict

作者: 飘渺的心意 | 来源:发表于2019-02-17 11:10 被阅读2次

    因为源码有点长,这里只截取重要部分

    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
    

    https://www.jianshu.com/p/dea99042f97f

    相关文章

      网友评论

          本文标题:async_model_to_dict

          本文链接:https://www.haomeiwen.com/subject/djqgeqtx.html