与Graphene SQLAlchemy接口类和节点接口的ID冲突

与Graphene SQLAlchemy接口类和节点接口的ID冲突,sqlalchemy,graphql,graphene-python,Sqlalchemy,Graphql,Graphene Python,我已经为数据库w/SQLalchemy中表示的多态实体编写了石墨烯模型 问题很简单: 我想创建一个界面,反映我的SQLAlchemy Graphene模型,但也可以是a)实现节点或b)不与节点冲突,并允许我检索模型的ID,而无需添加。。。在节点{id}上创建查询字符串 必须从基于ORM的接口中排除ID字段,或者字段与节点接口冲突,这样做是为了获得ID,然后需要在节点{ID}上添加…这很难看 我创建了一个扩展graphene.Interface的SQLAlchemyInterface对象。我的许多

我已经为数据库w/SQLalchemy中表示的多态实体编写了石墨烯模型

问题很简单:

我想创建一个界面,反映我的SQLAlchemy Graphene模型,但也可以是a)实现节点或b)不与节点冲突,并允许我检索模型的ID,而无需添加。。。在节点{id}上创建查询字符串

必须从基于ORM的接口中排除ID字段,或者字段与节点接口冲突,这样做是为了获得ID,然后需要在节点{ID}上添加…这很难看

我创建了一个扩展graphene.Interface的SQLAlchemyInterface对象。我的许多(但不是所有)模型都使用这个以及节点作为接口。第一个问题是,它包含一个ID字段,并且与节点接口冲突

为了不干扰节点,我排除了id字段,但后来发现我无法再直接在模型上查询id,不得不添加。。。在节点{id}上创建查询字符串

然后我决定让这个SQLAlchemyInterface扩展节点。我不喜欢这种方法,因为我需要为所有不一定需要实现SQLAlchemyInterface的模型使用另一个(命名的)节点接口

类SQLAlchemyInterface(节点): @类方法 def_u_init_子类_与_meta__( cls, 型号=无, 注册表=无, 仅_字段=(), 排除_字段=(), 连接\字段\工厂=默认\连接\字段\工厂, _meta=无, **选择权 ): _meta=SQLAlchemyInterfaceOptions(cls) _meta.name=f'{cls.\u u name\u_}节点' 自动排除列=排除自动生成的列(模型=模型) 排除\u字段+=自动排除\u列 断言是映射的类(模型)( 您需要在“{}.Meta,received”{}中传递一个有效的SQLAlchemy模型 ).格式(cls.\名称\型号) 如果不是注册中心: 注册表=获取全局注册表() 断言isinstance(注册表、注册表)( “{}中的属性注册表需要是的实例” '注册表,收到“{}”。' ).format(cls.\u名称\u,注册表) sqla\u fields=从属性中拉出字段( 构造_字段( 模型=模型, 注册表=注册表, 仅\u字段=仅\u字段, 排除\u字段=排除\u字段, 连接\字段\工厂=连接\字段\工厂 ), _as=字段 ) 如果不是_meta: _meta=SQLAlchemyInterfaceOptions(cls) _meta.model=模型 _meta.registry=registry connection=connection.create\u类型( “{}连接”。格式(cls.\uuuuuu name\uuuuuuu),节点=cls) 断言issubclass(连接,连接)( “该连接必须是连接。已接收{}” ).format(连接名) _meta.connection=连接 如果_meta.fields: _meta.fields.update(sqla_字段) 其他: _meta.fields=sqla\u字段 super(SQLAlchemyInterface,cls)。\uuuuuu init\u子类\uu与\uMeta(\uMeta=\uMeta,**选项) @类方法 def字段(cls、*ARG、**kwargs):#noqa:N802 返回节点字段(cls、*ARG、**kwargs) @类方法 def node_解析器(cls,仅_类型、根、信息、id): 返回cls.get_node_from_global_id(info,id,only_type=only_type) @类方法 def get_node_from_global_id(cls,info,global_id,only_type=None): 尝试: 节点:DeclarativeMeta=one或none(session=info.context.get('session'),model=cls.\u meta.model,id=global\u id) 返回节点 除例外情况外: 一无所获 @静力学方法 来自全局id(全局id)的def: 返回全局\u id @静力学方法 def到_全局_id(类型,id): 返回id 接口impls、模型+查询代码示例:

类自定义节点(节点):
类元:
名称='UuidNode'
@静力学方法
def到_全局_id(类型,id):
返回“{}:{}”。格式(类型,id)
@静力学方法
def get_node_from_global_id(信息,全局_id,仅_type=None):
类型,id=global_id.split(“:”)
如果仅为_类型:
#我们确保要检索的节点类型
#与字段类型中指示的相同
断言类型==仅\u类型。\u meta.name,“接收到不兼容的节点。”
如果类型==“用户”:
返回一个或无(session=info.context.get('session'),model=User,id=global\u id)
elif类型==“井”:
返回一个或无(session=info.context.get('session'),model=Well,id=global\u id)
类受控词汇表(SQLAlchemyInterface):
类元:
名称='Controlled词汇节点'
模型=BaseControlled词汇表
类跟踪属性(SQLAlchemyInterface):
类元:
名称='TrackEdentyNode'
模型=TrackedEntityModel
类请求(SQLAlchemyObject类型):
“”“请求节点。”“”
类元:
模型=请求模型
接口=(TrackedEntity,)
类用户(SQLAlchemyObject类型):
“用户节点”
类元:
model=UserModel
接口=(CustomNode,)
类CvFormFieldValueType(SQLAlchemyObject类型):
类元:
模型=CvFormFieldValueTypeModel
接口=(受控词汇表)
公共_字段_kwargs={'id':graphene.UUID(必需=False),'label':graphene.String(必需=False)}
类查询(graphene.ObjectType):
“”“为GraphQL API查询对象。”“”
node=CustomNode.Field()
te_节点=TrackedEntity.Field()
cv_node=Controlled词汇表.Field()
#非跟踪实体:
用户:列表[用户]=SQLAlchemyConnectionField(用户)
#任何跟踪实体的通用查询:
跟踪的实体:列表[TrackedEntity]=Filte
query queryTracked {
      trackedEntities{
            id
            (other fields)
            ... on Request {
                    (request specific fields)
             }
       }