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

Add a feature to be able to add additional arguments in DjangoModelFormMutation and DjangoFormMutation

Open MamoonAhmad opened this issue 3 years ago • 6 comments

Describe the solution you'd like DjangoModelFormMutation only reads forms fields. But I dont have the option to override a form field to change its type. Sometimes a user may have a complex object stored in database and he/she cleans and re-creates the object on retrieval. GraphQL has the ability to predefine the types and create, send or receive complex objects. It would be a good feature to override or add additional field in the inputs.

Describe alternatives you've considered Django forms does not support lots of different data types which GraphQL does. So as a backend developer, I am limited.

MamoonAhmad avatar Feb 03 '21 22:02 MamoonAhmad

How would the custom fields work with the internal form logic of validating and saving? Currently the form based mutations punt these operations to the form itself, if we're adding additional GraphQL fields then the mutation would need to treat those differently for them to work.

zbyte64 avatar Feb 04 '21 00:02 zbyte64

In this case it would probably make more sense to use a traditional mutation and set the arguments yourself in my opinion.

tcleonard avatar Feb 04 '21 11:02 tcleonard

@tcleonard The reason we use ModelFormMutation is to be able to not write all the inputs of a model. Re-writing all the model fields is pretty tedious. Also, it is prone to error. If we change model, we might have to change the inputs again.

MamoonAhmad avatar Feb 04 '21 13:02 MamoonAhmad

@zbyte64 What I mean is that if we have a JSON stored in database of a particular type. We should be able to get this input in the form of actual object type which is stored. Form does not support complex data types hence reading form fields cannot emit a correct data type. While it is true, that form validation can take care of complex objects in its clean method. But what I am suggesting is to put extra data validation layer as Graphql is capable of that.

MamoonAhmad avatar Feb 04 '21 13:02 MamoonAhmad

@zbyte64 @tcleonard This is a code sample which I am using locally. I have implemented a modified version of DjangoModelFormMutation.

class PurchaseArguments(ModifiedDjangoModelFormMutation):
    class Meta:
        abstract = True
    class Arguments:
        purchasable_items = graphene.Field(graphene.List(of_type=PurchasableItemsInput), required=True)

    def clean(self, **input):
        utils.from_global_id_multiple(["customer", "store"], input)
        for item in input.get("purchasable_items"):
            utils.from_global_id_multiple(["purchasable_item"], item)
        
        return input


class AddPurchase(PurchaseArguments):
    class Meta:
        form_class = forms.AddPurchase
        exclude_fields=["id"]

In class PurchaseArguments there is an Arguments class. ModifiedDjangoModelFormMutation reads Arguments class' fields and overrides the fields or adds additional fields (depends on the use case).

clean method in PurchaseArguments in overrode method of ModifiedDjangoModelFormMutation. Intention of this methods is to clean input arguments before being sent to the form. This helps also convert the base64 Graphql IDs before sent to the form.

MamoonAhmad avatar Feb 04 '21 13:02 MamoonAhmad

I think this should be added to the library.

Django offers the option to override the fields on a model form so django graphene should support this as well.

# plain old django

class SomeModelForm(forms.ModelForm):
  class Meta:
      model = SomeModel
      fields = ('some_field',)
  some_field = forms.CharField()

My case which led me here is wanting to use a custom date scalar. A modal form with a date field will use the built in date scalar which wants input of form yyyy-mm-dd.

rossm6 avatar Oct 16 '21 13:10 rossm6