在运行时石墨烯上创建动态模式 [英] 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":",选项":[{"id":"author_faname",标签":样品样品","type":"text","required":是的,占位符":一二三四"},{"id":"author_enname","label":"Sample label","type":"text","required":是的,占位符":"Sample Placeholder"}]}
这是基于该内容类型存储在数据库中的内容:
<代码> {"id":"9rqgbrox10","content_type":作者",数据":{"author_fname":"Jimmy","author_ename":"Hello"}}
现在,由于我的模型没有在代码中声明,并且它们完全在DB中声明,因此我想即时创建自己的模式,而且我不知道哪种解决方案是最好的解决方案.我知道应该有办法,因为其他无头CMS项目正在提供这种方法.
提前谢谢!
基本上,架构是这样创建的:
class MyType(graphene.ObjectType):东西= graphene.String()Query(graphene.ObjectType)类:值= graphene.Field(MyType)schema = graphene.Schema(query =查询,类型= [MyType])
首先,为了添加某种动态效果,您很可能希望将上述代码包装在类似 create_schema()
的函数中.
然后,当您想在运行时动态创建类时,可以按以下方式重写上面的代码:
def create_schema():MyType = type('MyType',(graphene.ObjectType,),{'某物':graphene.String(),})Query = type('Query',(graphene.ObjectType,),{'值':graphene.Field(MyType),})返回graphene.Schema(查询=查询,类型= [MyType])
对于您的示例,它可能看起来像这样:
def make_resolver(record_name,record_cls):def解析器(自身,信息):数据= ...返回record_cls(...)resolver .__ name__ ='resolve_%s'%记录名称返回解析器def create_schema(db):record_schemas = {}对于db.get_record_types()中的record_type:classname = record_type ['id'].title()#'作者'字段= {}对于record_type ['options']中的选项:field_type = {'文字':graphene.String,...} [option ['type']fields [option ['id']] = field_type()#可能添加标签作为描述?rec_cls =类型(班级名称,(graphene.ObjectType,),领域name = record_type ['name'],description = record_type ['desc'],)record_schemas [record_type ['id']] = rec_cls#以类似方式创建查询字段= {}对于密钥,请在record_schemas中进行记录:字段[关键字] = graphene.Field(rec)字段['resolve_%s'%键] = make_resolver(键,记录)查询=类型('查询',(graphene.ObjectType,),字段)返回graphene.Schema(查询=查询,类型=列表(record_schemas.values()))
请注意,如果您尝试将新字段插入到现有的类中,像这样- MyType.another_field = graphene.String()
,那就行不通:这是因为当实例化 graphene.ObjectType
类时,它的所有字段都记录在 self._meta.fields
OrderedDict中.并且更新它并不像 MyType._meta.fields ['another_field'] = thefield
一样简单-有关详细信息,请参见 graphene.ObjectType .__ init_subclass_with_meta __
的代码.>
因此,如果您的架构是动态更改的,那么最好是从头开始完全重新创建它,而不是对其进行修补.
I almost spent 3 days to find a way for creating a dynamic schema in python graphene. the only related result I could find is the below link: https://github.com/graphql-python/graphene/blob/master/graphene/types/dynamic.py But I couldn't find any documentation for it.
The whole idea is to create a dynamic schema. I want to provide a GraphQL compatible API that makes users able to query my contents even if Models are not defined in the code. In other words, I want to create Models on the fly. I have no idea about what shall I do.
It would be a great favor if you can provide an example for that.
Update :
My Project is a Headless CMS which has a feature that users can create their own content types and I want to provide a GraphQL interface to make everything easier and more flexible.
Here is example of my Content Types in 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"
}
]
}
And Here is Stored content in DB based on that content type :
{
"id": "9rqgbrox10",
"content_type": "author",
"data":{
"author_fname":"Jimmy",
"author_ename":"Hello"
}
}
Now as my Models are not declared in Code and they are completely in DB, I want to make my schemas on the fly and I don't know what is best the solution for this. I know there should be a way because the other Headless CMS Projects are providing this.
Thanks in advance!
Basically, schema is created something like this:
class MyType(graphene.ObjectType):
something = graphene.String()
class Query(graphene.ObjectType):
value = graphene.Field(MyType)
schema = graphene.Schema(query=Query, types=[MyType])
First, in order to add some kind of dynamics, you will most likely want to wrap the above code in a function like create_schema()
.
Then, when you want to dynamically create a class during runtime, the above code can be rewritten like this:
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])
For your example it could look something like this:
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()))
Note that if you try to insert new fields into already existing class,
like this - MyType.another_field = graphene.String()
,
then it won't work: that is because when graphene.ObjectType
class is instantiated,
all its fields are recorded in self._meta.fields
OrderedDict.
And updating it is not as straightforward as just MyType._meta.fields['another_field'] = thefield
- see the code of graphene.ObjectType.__init_subclass_with_meta__
for details.
So if your schema is dynamically changed then it might be better to fully re-create it from scratch than to patch it.
这篇关于在运行时石墨烯上创建动态模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!