graphql-python / graphene-pydantic

Integrate GraphQL with your Pydantic models
Other
229 stars 44 forks source link

Mapping pydantic.Field.alias attr as graphene.Field.name #82

Closed conao3 closed 1 year ago

conao3 commented 1 year ago

This PR fixes #38.

Graphene sample

In other words, the same behavior as this working graphene can be made to work for a pydantic model

import graphene

class Model(graphene.ObjectType):
    class_ = graphene.String(name='class')

class Query(graphene.ObjectType):
    model = graphene.Field(Model)

    @staticmethod
    def resolve_model(parent, info):
        return Model(class_='test')

schema = graphene.Schema(query=Query)
print(schema)
print(schema.execute('{model {class}}'))

Graphene-pydantic sample

After this patch, this script works, so perhaps this patch is good. I have not been able to fully verify the other behavior.

import graphene
import pydantic

import graphene_pydantic

class Model(pydantic.BaseModel):
    class_: str = pydantic.Field(alias='class')

class GrapheneModel(graphene_pydantic.PydanticObjectType):
    class Meta:
        model = Model

model = Model(**{'class': 'test'})
print(model)

class Query(graphene.ObjectType):
    model = graphene.Field(GrapheneModel)
    hello = graphene.String()

    @staticmethod
    def resolve_model(parent, info):
        return Model(**{'class': 'test'})

schema = graphene.Schema(query=Query)
print(schema)
print(schema.execute('{model {class}}'))

sample output

class_='test'
type Query {
  model: GrapheneModel
  hello: String
}

type GrapheneModel {
  class: String!
}

ExecutionResult(data={'model': {'class': 'test'}}, errors=None)

Advice is welcome!

necaris commented 1 year ago

From looking at Pydantic's docs, for all the supported versions this should be great -- field.alias defaults to name if it's not set.

conao3 commented 1 year ago

As you pointed out, I thought this patch would work correctly because pydantic returns the default name if no alias is set, but graphene adopts the explicitly set snake case field name in the schema as it is, so the field name that used to automatically convert to camelCase were not being converted. Therefore, the field names are now set to graphene's name only when alias is set.

In fact, pydantic's alias should be set in snake case and graphql should be converted depending on auto_camelcase in graphene.Schema (document), but this care I will address in another PR.

necaris commented 1 year ago

@conao3 thank you for the further testing! I have approved the PR, but it looks like the tests are failing for an unrelated reason, so I will have to fix that first.