graphene-pydantic icon indicating copy to clipboard operation
graphene-pydantic copied to clipboard

Pydantic - Graphene throws error for discriminator input objects.

Open maheshchowdam523 opened this issue 3 years ago • 3 comments

I am using graphene-pydantic to generate a GraphQL schema for my mutation. I have gone through the documentation and it's working fine for all the types but the problem is when I use discriminators in the modules. Below is the sample code with discriminators and that's throwing an error.

from graphene_pydantic import PydanticInputObjectType, PydanticObjectType
import graphene
from typing import Literal, Union
from pydantic import BaseModel, Field


class Cat(BaseModel):
    pet_type: Literal['cat']
    meows: int


class Dog(BaseModel):
    pet_type: Literal['dog']
    barks: float


class Lizard(BaseModel):
    pet_type: Literal['reptile', 'lizard']
    scales: bool


class Model(BaseModel):
    pet: Union[Cat, Dog, Lizard] = Field(..., discriminator='pet_type')
    n: int


# print(Model(pet={'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit'}, n=1))


class Input(PydanticInputObjectType):
    class Meta:
        model = Model
        # exclude specified fields
        exclude_fields = ("id",)


class Output(PydanticObjectType):
    class Meta:
        model = Model
        # exclude specified fields
        exclude_fields = ("id",)


class CreateAnimal(graphene.Mutation):
    class Arguments:
        input = Input()

    output = Output

    @staticmethod
    def mutate(parent, info, input):
        print(input)
        # save model here
        return input


class Mutation(graphene.ObjectType):
    createPerson = CreateAnimal.Field()


schema = graphene.Schema(mutation=Mutation)
print(schema)

The error getting from graphene is like below and it is like a generalized error.

File "\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\type\definition.py", line 1338, in fields    raise TypeError(f"{self.name} fields cannot be resolved. {error}")
TypeError: Input fields cannot be resolved. The input field type must be a GraphQL input type.

Can someone help on this?

maheshchowdam523 avatar Apr 13 '22 16:04 maheshchowdam523

@maheshchowdam523 try to define input and output schemas for Cat, Dog and Lizard models

dima-dmytruk23 avatar Apr 19 '22 13:04 dima-dmytruk23

@dima-dmytruk23, I have tried defining the schemas for individual models as well, but still, the error is the same. If I remove discriminator it is working perfectly. Below is the code.

from graphene_pydantic import PydanticInputObjectType, PydanticObjectType
import graphene
from typing import Literal, Union
from pydantic import BaseModel, Field


class Cat(BaseModel):
    pet_type: Literal['cat']
    meows: int


class Dog(BaseModel):
    pet_type: Literal['dog']
    barks: float


class Lizard(BaseModel):
    pet_type: Literal['reptile', 'lizard']
    scales: bool


class Model(BaseModel):
    pet: Union[Cat, Dog, Lizard] = Field(..., discriminator='pet_type')
    n: int


print(Model(pet={'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit'}, n=1))


class CatInput(PydanticInputObjectType):
    class Meta:
        model = Cat
        fields = "__all__"


class DogInput(PydanticInputObjectType):
    class Meta:
        model = Dog
        fields = "__all__"


class LizardInput(PydanticInputObjectType):
    class Meta:
        model = Lizard
        fields = "__all__"


class CatOutput(PydanticObjectType):
    class Meta:
        model = Cat
        fields = "__all__"


class DogOutput(PydanticObjectType):
    class Meta:
        model = Dog
        fields = "__all__"


class LizardOutput(PydanticObjectType):
    class Meta:
        model = Lizard
        fields = "__all__"


class Input(PydanticInputObjectType):
    class Meta:
        model = Model
        # exclude specified fields
        exclude_fields = ("id",)


class Output(PydanticObjectType):
    class Meta:
        model = Model
        # exclude specified fields
        exclude_fields = ("id",)


class CreateAnimal(graphene.Mutation):
    class Arguments:
        input = Input()

    output = graphene.Field(Output)

    @staticmethod
    def mutate(parent, info, input):
        print(input)
        # save model here
        return input


class Mutation(graphene.ObjectType):
    createPerson = CreateAnimal.Field()


schema = graphene.Schema(mutation=Mutation)
print(schema)

maheshchowdam523 avatar Apr 23 '22 05:04 maheshchowdam523

It looks like this discriminator behavior is new in Pydantic 1.9 -- there appear to be a few new features that we don't currently support, including this. The way to handle this with graphene is to add a resolve_type classmethod to handle the discrimination -- a PR to do this would be welcome.

necaris avatar Apr 23 '22 20:04 necaris