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

Ale*_*and 3 python sqlalchemy graphene-python

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

我的类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.")
Run Code Online (Sandbox Code Playgroud)

我的类CreatePlanetInput用于定义石墨烯输入对象类型。请注意,它从上面定义的类继承其属性PlanetAttribute

class CreatePlanetInput(graphene.InputObjectType, PlanetAttribute):
    """Arguments to create a planet."""
    pass
Run Code Online (Sandbox Code Playgroud)

我的类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)
Run Code Online (Sandbox Code Playgroud)

PlanetAttribute我不想在类中手动声明突变输入,而是从我的 SQLALchemy 类动态生成它们ModelPlanet,其定义如下:

class ModelPlanet(Base):
    """Planet model."""

    __tablename__ = 'planet'

    id = Column('id', Integer, primary_key=True, doc="Id of the person.")
    name = Column('name', String, doc="Name of the planet.")
    rotation_period = Column('rotation_period', String, doc="Rotation period of the planet.")
    orbital_period = Column('orbital_period', String, doc="Orbital period of the planet.")
    diameter = Column('diameter', String, doc="Diameter of the planet.")
    climate = Column('climate', String, doc="Climate period of the planet.")
    gravity = Column('gravity', String, doc="Gravity of the planet.")
    terrain = Column('terrain', String, doc="Terrain of the planet.")
    surface_water = Column('surface_water', String, doc="Surface water of the planet.")
    population = Column('population', String, doc="Population of the planet.")
    created = Column('created', String, doc="Record created date.")
    edited = Column('edited', String, doc="Record last updated date.")
    url = Column('url', String, doc="URL of the planet in the Star Wars API.")

    peopleList = relationship(ModelPeople, backref='planet')
Run Code Online (Sandbox Code Playgroud)

你将如何进行?

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

Fed*_*lto 5

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

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
        )
Run Code Online (Sandbox Code Playgroud)

您可以将其用于:

class CreatePlanetInput(SQLAlchemyInputObjectType):
    class Meta:
        model = ModelPlanet
        exclude_fields = ('id', )
Run Code Online (Sandbox Code Playgroud)

我试图让它的行为与SQLAlchemyObjectType, 所以only_fieldsexclude_fields应该按预期工作。

我还添加了一个optional_fields,使其不需要,有利于更新突变。

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