从SQLAlchemy类属性生成石墨烯突变输入

时间:2018-02-15 11:56:38

标签: python sqlalchemy graphene-python

我目前为我的项目定义了以下突变:

我的班级CAST AS用于定义用作我的突变输入的石墨烯字段

PlanetAttribute

我的班级class PlanetAttribute: name = graphene.String(required=True, description="Name of the planet.") rotation_period = graphene.String(default_value="unknown", description="Rotation period of the planet.") orbital_period = graphene.String(default_value="unknown", description="Orbital period of the planet.") diameter = graphene.String(default_value="unknown", description="Diameter of the planet.") climate = graphene.String(default_value="unknown", description="Climate period of the planet.") gravity = graphene.String(default_value="unknown", description="Gravity of the planet.") terrain = graphene.String(default_value="unknown", description="Terrain of the planet.") surface_water = graphene.String(default_value="unknown", description="Surface water of the planet.") population = graphene.String(default_value="unknown", description="Population of the planet.") url = graphene.String(default_value="unknown", description="URL of the planet in the Star Wars API.") 用于定义Graphene输入对象类型。请注意,它从上面定义的CreatePlanetInput类继承其属性。

PlanetAttribute

我的班级class CreatePlanetInput(graphene.InputObjectType, PlanetAttribute): """Arguments to create a planet.""" pass 是我的Graphene突变类,它以CreatePlanet类作为参数。

CreatePlanetInput

我不想在class CreatePlanet(graphene.Mutation): """Create a planet.""" planet = graphene.Field(lambda: Planet, description="Planet created by this mutation.") class Arguments: input = CreatePlanetInput(required=True) def mutate(self, info, input): data = utils.input_to_dictionary(input) data['created'] = datetime.utcnow() data['edited'] = datetime.utcnow() planet = ModelPlanet(**data) db_session.add(planet) db_session.commit() return CreatePlanet(planet=planet) 类中手动声明变异输入,而是从我的SQLALchemy类PlanetAttribute动态生成它们,其定义如下:

ModelPlanet

你会怎么做?

请注意,我还在此处发布了问题:https://github.com/graphql-python/graphene-sqlalchemy/issues/112

1 个答案:

答案 0 :(得分:2)

我解决了创建这个类的问题:

from graphene.types.utils import yank_fields_from_attrs
from graphene.utils.subclass_with_meta import SubclassWithMeta_Meta
from graphene_sqlalchemy.registry import get_global_registry
from graphene_sqlalchemy.types import construct_fields

class SQLAlchemyInputObjectType(graphene.InputObjectType):
    @classmethod
    def __init_subclass_with_meta__(  # pylint: disable=arguments-differ
        cls, model=None, registry=None, only_fields=(), exclude_fields=(),
        optional_fields=(), **options
    ):
        if not registry:
            registry = get_global_registry()

        sqla_fields = yank_fields_from_attrs(
            construct_fields(model, registry, only_fields, exclude_fields),
            _as=graphene.Field,
        )

        for key, value in sqla_fields.items():
            if key in optional_fields:
                type_ = value.type if isinstance(
                    value.type, SubclassWithMeta_Meta) else value.type.of_type
                value = type_(
                    description=value.description
                )
            setattr(cls, key, value)

        super(SQLAlchemyInputObjectType, cls).__init_subclass_with_meta__(
            **options
        )

您可以将其用于:

class CreatePlanetInput(SQLAlchemyInputObjectType):
    class Meta:
        model = ModelPlanet
        exclude_fields = ('id', )

我尝试使其与SQLAlchemyObjectType的行为相似,因此only_fieldsexclude_fields应该按预期工作。

我还添加了optional_fields,这使得它不是必需的,适用于更新变异。

它确实处理简单的情况,比如标量字段。关系,如peopleList,您需要手动声明。