graphql-python / graphene-django

Build powerful, efficient, and flexible GraphQL APIs with seamless Django integration.
http://docs.graphene-python.org/projects/django/en/latest/
MIT License
4.31k stars 769 forks source link

DjangoFormMutation should allow filtering of input and output separately #933

Open jtratner opened 4 years ago

jtratner commented 4 years ago

DjangoFormMutation by default filters both input and output fields based on only_fields and exclude_fields. Ideally it'd allow you to filter input and output separately. (I'm going to put up a PR alongside this, but figured it was best form to have an issue too).

Desired Behavior vs. Actual Behavior

Desired Behavior: Mutation that has a payload with only clientMutationId + my custom output field, while still having all input fields Actual Behavior: either have to filter out all input fields (making form unusable) or end up pushing out all of the input fields into the outputted payload (which doesn't quite make sense to me)

Background and Example

Imports + model definition + form definition

from graphene_django import DjangoObjectType
from graphene import relay, ObjectType, Int
from graphene_django.forms.types import ErrorType
from graphene_django.forms.mutation import DjangoFormMutation
from spar_web.core.models import Report
from django import forms
from django.db import models
import graphene

class Report(models.Model):
    display_name = models.CharField(max_length=255)
    config = models.CharField(max_length=255)
    directory = models.CharField(max_length=255)

class CreateReportForm(forms.Form):
    display_name = forms.CharField()
    report_type = forms.CharField()
    directory = forms.CharField()
    config = forms.CharField(required=False)

    def clean(self):
        if self.errors:
            return
        cleaned_data = super().clean()
        if not cleaned_data.get('config'):
            # dummy example
            cleaned_data['config'] = cleaned_data['report_type'] + 'config'
        return cleaned_data
class ReportNode(DjangoObjectType):
    class Meta:
        model = Report
        interfaces = (relay.Node,)

class CreateReportMutation(DjangoFormMutation):
    report = graphene.Field(ReportNode)

    class Meta:
        form_class = Create
        only_fields = ['report']

    @classmethod
    def perform_mutate(cls, form, info):
        data = form.cleaned_data
        obj = Report.objects.create(
            display_name=data['display_name'],
            directory=data['directory'],
            config=data['config']
        )
        kwargs = {'report': obj}
        return cls(errors=[], **kwargs)

class Query(graphene.ObjectType):
    report = relay.Node.Field(ReportNode)

class Mutation(graphene.ObjectType):
    create_report = CreateReportMutation.Field()

schema = graphene.Schema(
    query=Query,
    mutation=Mutation
)
jtratner commented 4 years ago

(pushed PR with example in #934 :) )

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

ruohola commented 3 years ago

Any update on this?