Creating Dynamic Schema on Runtime Graphene
我几乎花了3天的时间来找到一种在python石墨烯中创建动态模式的方法。
我唯一可以找到的相关结果是以下链接:
https://github.com/graphql-python/graphene/blob/master/graphene/types/dynamic.py
但是我找不到关于它的任何文档。
整个想法是创建一个动态模式。我想提供一个GraphQL兼容的API,即使代码中没有定义模型,用户也可以查询我的内容。换句话说,我想即时创建模型。我不知道该怎么办。
如果您可以提供一个示例,将非常有帮助。
更新:
我的项目是无头CMS,它具有用户可以创建自己的内容类型的功能,我想提供一个GraphQL界面来使所有操作变得更加轻松和灵活。
这是我在DB中的内容类型的示例:
{
"id":"author",
"name":"Book Author",
"desc":"",
"options":[
{
"id":"author_faname",
"label":"Sample Sample",
"type":"text",
"required": true,
"placeholder":"One Two Three Four"
},
{
"id":"author_enname",
"label":"Sample label",
"type":"text",
"required": true,
"placeholder":"Sample Placeholder"
}
]
}
这是基于该内容类型在数据库中存储的内容:
"id":"9rqgbrox10",
"content_type":"author",
"data":{
"author_fname":"Jimmy",
"author_ename":"Hello"
}
}
现在,因为我的模型没有在代码中声明,并且它们完全在DB中声明,所以我想即时创建自己的模式,而且我不知道什么是最佳的解决方案。我知道应该有办法,因为其他无头CMS项目正在提供这种方法。
谢谢!
基本上,架构是这样创建的:
1 2 3 4 5 6 7 | class MyType(graphene.ObjectType): something = graphene.String() class Query(graphene.ObjectType): value = graphene.Field(MyType) schema = graphene.Schema(query=Query, types=[MyType]) |
首先,为了增加某种动态效果,您很可能希望将上述代码包装在类似
然后,当您想在运行时动态创建类时,可以将上述代码重写为:
1 2 3 4 5 6 7 8 9 10 | def create_schema(): MyType = type('MyType', (graphene.ObjectType,), { 'something': graphene.String(), }) Query = type('Query', (graphene.ObjectType,), { 'value': graphene.Field(MyType), }) return graphene.Schema(query=Query, types=[MyType]) |
对于您的示例,它可能看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | def make_resolver(record_name, record_cls): def resolver(self, info): data = ... return record_cls(...) resolver.__name__ = 'resolve_%s' % record_name return resolver def create_schema(db): record_schemas = {} for record_type in db.get_record_types(): classname = record_type['id'].title() # 'Author' fields = {} for option in record_type['options']: field_type = { 'text': graphene.String, ... }[option['type'] fields[option['id']] = field_type() # maybe add label as description? rec_cls = type( classname, (graphene.ObjectType,), fields, name=record_type['name'], description=record_type['desc'], ) record_schemas[record_type['id']] = rec_cls # create Query in similar way fields = {} for key, rec in record_schemas: fields[key] = graphene.Field(rec) fields['resolve_%s' % key] = make_resolver(key, rec) Query = type('Query', (graphene.ObjectType,), fields) return graphene.Schema(query=Query, types=list(record_schemas.values())) |
请注意,如果您尝试将新字段插入到现有的类中,
这样-
那就行不通了:这是因为当实例化
它的所有字段都记录在
并且更新它不像
因此,如果您的架构是动态更改的,那么最好是从头开始完全重新创建它,而不是对其进行修补。