По сути, схема создается примерно так:
class MyType(graphene.ObjectType):
something = graphene.String()
class Query(graphene.ObjectType):
value = graphene.Field(MyType)
schema = graphene.Schema(query=Query, types=[MyType])
Во-первых, чтобы добавить какую-то динамику, вы, скорее всего, захотите обернуть вышеуказанный код в функцию, подобную create_schema()
.
Затем, когда вы хотите динамически создать класс во время выполнения, приведенный выше код можно переписать так:
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])
Для вашего примера это может выглядеть примерно так:
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()))
Обратите внимание, что если вы попытаетесь вставить новые поля в уже существующий класс, например - MyType.another_field = graphene.String()
, то это не сработает: это потому, что когда создается экземпляр класса graphene.ObjectType
, записываются все его поляв self._meta.fields
OrderedDict.И обновить его не так просто, как просто MyType._meta.fields['another_field'] = thefield
- подробности см. В коде graphene.ObjectType.__init_subclass_with_meta__
.
Так что, если ваша схема динамически изменяется, то может быть лучше полностью заново создать ее с нуля, чемзалатать его.