5

Say I have,

class PersonNode(DjangoObjectType):
    class Meta:
        model = Person
        fields = ('first_name', 'last_name', 'age',
                  'sex', 'alive', 'unique_identifier',)
        filter_fields = ('first_name', 'last_name', 'age',
                         'sex', 'alive', 'unique_identifier',)
        interfaces = (graphene.relay.Node,)

class PersonNodeInput(graphene.InputObjectType):
    first_name = graphene.String()
    last_name = graphene.String()
    # rest of person model fields

class Valid(graphene.ObjectType):
    ok = graphene.Boolean()

class Query(graphene.ObjectType):
    validate_person = graphene.Field(Valid, args={
                                     "data": PersonNodeInput()})
    person = graphene.relay.Node.Field(PersonNode)
    all_people = DjangoFilterConnectionField(PersonNode)

    def resolve_validate_person(root, info, data):
        print("resolve validate person")
        return Valid(ok=True)

Is it possible to avoid writing out PersonNodeInput? It would be nice if you could subclass something like "DjangoInputObjectType" and specify the model and fields you want in a Meta attribute.

user1849962
  • 1,273
  • 1
  • 11
  • 16

3 Answers3

2

We've been using this Graphene Django CUD library that tries to remove some of the boilerplate involved in defining mutations.

Adapting your case to their example would look something like

from graphene_django_cud.mutations import DjangoCreateMutation

class CreatePersonMutation(DjangoCreateMutation):
    class Meta:
        model = Person

class PersonMutations(graphene.ObjectType):
    create_person = CreateUserMutation.Field()

schema = Schema(mutation=PersonMutations)

I don't know how well it works with Relay nodes, because we're not using Relay.

bjmc
  • 2,970
  • 2
  • 32
  • 46
1

There is a PR in graphene-django https://github.com/graphql-python/graphene-django/pull/1325 (Adds DjangoFormInputObjectType (InputObjectType derived class) which can retrieve fields from django form):

class MyDjangoFormInput(DjangoFormInputObjectType):

    # any other fields can be placed here as well as
    # other djangoforminputobjects and intputobjects

    class Meta:
        form_class = MyDjangoModelForm


class SomeMutation(graphene.Mutation):
    class Arguments:
        data = MyDjangoFormInput(required=True)

    @staticmethod
    def mutate(_root, _info, data):
        form_inst = MyDjangoModelForm(data=data)
        if form_inst.is_valid():
            model_inst = form_inst.save(commit=False)

        # ...
ndpu
  • 22,225
  • 6
  • 54
  • 69
  • 1
    This is now merged and published in graphene-django v3.1.1 (thanks ndpu!). Docs here https://github.com/graphql-python/graphene-django/blob/2358bd30a452859c50b6bdacdc27ae518716153b/docs/mutations.rst#djangoforminputobjecttype – Steven D. Jun 11 '23 at 19:17
0

you might want to check out the dicussion here. charlesverdad's answer did the trick for me:

from rest_framework import serializers
from graphene_django.rest_framework.serializer_converter import convert_serializer_to_input_type

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        exclude = ('profile',)

class PersonArgsInput(convert_serializer_to_input_type(PersonSerializer)):
    create = graphene.Boolean(required=True)

class PersonsMutation(graphene.Mutation):
    person_set = graphene.List(PersonType)
    class Arguments:
        person_set = graphene.List(PersonArgsInput)
    def mutate():
        ...

I like this way because I use the Django serializer anyway. All credits to Charles Verdad.