我想自动为SQLAlchemy模型列表自动生成一个graphene-python模式。
我环顾四周,并在这里使用Django模型发现了类似的问题:Graphene-Python: automatic schema generation from Django model
他提出了一个看起来像这样的元类:
class AutoSchemaMeta(type):
def __new__(meta, clsname, superclasses, attributedict):
new_class = type(clsname, superclasses, attributedict)
for app_name in new_class.app_models.split(","):
app_models = apps.get_app_config(app_name.strip()).get_models()
for model in app_models:
model_name = model._meta.model_name
_model_name = c2u(model_name)
if hasattr(new_class, _model_name):
continue
_node_class = type("{}Node".format(model_name.title()),
(SQLAlchemyObjectType,),
{"Meta": {"model": model, "interfaces": (Node,), "filter_fields": []}})
# register(_node_class) not needed, done by SQLAlchemyObjectType
setattr(new_class, "all_{}".format(s2p(_model_name)), FilteredConnectionField(_node_class))
setattr(new_class, _model_name, Node.Field(_node_class))
print(new_class.__dict__)
return new_class
class Query(metaclass=AutoSchemaMeta):
app_models = 'app1,app2'
我正想做同样的事情,只是我对他在这4行代码中的所作所为感到困惑:
for app_name in new_class.app_models.split(","):
app_models = apps.get_app_config(app_name.strip()).get_models()
for model in app_models:
model_name = model._meta.model_name
在给定包含SQLAlchemy模型的文件/目录列表的情况下,任何人都可以帮助建议采取这种方法的方法吗?
示例orm目录/型号: main.orm.models: model1.py:
class Model1(Base):
__tablename__ = 'model_one'
id = Column(UUID)
model2.py:
class Model2(Base):
___tablename__ = 'model_two'
id = Column(UUID)
这些类型的自动生成:
import graphene
from main.orm.models import Model1 as Model1Model, Model2 as Model2Model
class Model1Node(SQLalchemyObjectType):
class Meta:
model = Model1Model
interfaces = (Node,)
class Model2Node(SQLalchemyObjectType):
class Meta:
model = Model2Model
interfaces = (Node,)
class Query(graphene.ObjectType):
model1_node = Node.Field(Model1Node)
all_model1_nodes = FilteredConnectionField(Model1Node)
model2_node = Node.Field(Model2Node)
all_model2_nodes = FilteredConnectionField(Model2Node)
包括FilteredConnectionField以帮助解决问题
class FilteredConnectionField(SQLAlchemyConnectionField):
def __init__(self, type_, *args, **kwargs):
model = type_._meta.model
kwargs.setdefault("filter", create_filter_argument(model))
super(FilteredConnectionField, self).__init__(type_, *args, **kwargs)
@classmethod
def get_query(cls, model, info: ResolveInfo, filter=None, sort=None, group_by=None, order_by=None, **kwargs):
query = super().get_query(model, info, sort=None, **kwargs)
# columns = inspect(model).columns.values()
from core.main.graphene.util.sqla_types import SQLAlchemyInputObjectType
for filter_name, filter_value in kwargs.items():
model_filter_column = getattr(model, filter_name, None)
if not model_filter_column:
continue
if isinstance(filter_value, SQLAlchemyInputObjectType):
filter_model = filter_value.sqla_model
q = super().get_query(filter_model, info, sort=None, **kwargs)
# noinspection PyArgumentList
query.filter(model_filter_column == q.filter_by(**filter_value).one())
if filter:
for filter_name, filter_value in filter.items():
query = filter_query(query, model, filter_name, filter_value)
return query
@classmethod
def resolve_connection(cls, connection_type, model, info, args, resolved):
filters = args.get("filter", {})
field = getattr(info.schema._query, camel_to_snake(info.field_name))
if field and hasattr(field, 'required') and field.required:
required_filters = [rf.key for rf in field.required]
if required_filters:
missing_filters = set(required_filters) - set(filters.keys())
if missing_filters:
raise Exception(missing_filters)
return super(FilteredConnectionField, cls).resolve_connection(
connection_type, model, info, args, resolved)