From 9aeee283fa413243cb533d260609a89f4b4ddcff Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sun, 28 Oct 2018 21:40:19 +0000 Subject: [PATCH] Unify support for models and model form --- graphene_django/forms/mutation.py | 111 +++++++------------ graphene_django/forms/tests/test_mutation.py | 44 ++++---- 2 files changed, 61 insertions(+), 94 deletions(-) diff --git a/graphene_django/forms/mutation.py b/graphene_django/forms/mutation.py index 0c1c89b..a2ac9e0 100644 --- a/graphene_django/forms/mutation.py +++ b/graphene_django/forms/mutation.py @@ -92,7 +92,8 @@ class BaseDjangoFormMutation(ClientIDMutation): class DjangoFormMutationOptions(MutationOptions): form_class = None - + model = None + return_field_name = None class DjangoFormMutation(BaseDjangoFormMutation): class Meta: @@ -100,7 +101,12 @@ class DjangoFormMutation(BaseDjangoFormMutation): @classmethod def __init_subclass_with_meta__( - cls, form_class=None, only_fields=(), exclude_fields=(), **options + cls, + form_class=None, + return_field_name=None, + only_fields=(), + exclude_fields=(), + **options ): if not form_class: @@ -108,19 +114,46 @@ class DjangoFormMutation(BaseDjangoFormMutation): form = form_class() input_fields = fields_for_form(form, only_fields, exclude_fields) - output_fields = fields_for_form(form, only_fields, exclude_fields) input_fields = yank_fields_from_attrs(input_fields, _as=InputField) base_name = cls.__name__ + _meta = DjangoFormMutationOptions(cls) + cls.Errors = create_errors_type( "{}Errors".format(base_name), input_fields ) + # TODO: output + + + if hasattr(form, '_meta') and hasattr(form._meta, 'model'): + model = form._meta.model + _meta.model = model + + registry = get_global_registry() + model_type = registry.get_type_for_model(model) + return_field_name = return_field_name + + if "id" not in exclude_fields: + input_fields["id"] = graphene.ID() + + if not return_field_name: + model_name = model.__name__ + return_field_name = model_name[:1].lower() + model_name[1:] + + output_fields = OrderedDict() + output_fields[return_field_name] = graphene.Field(model_type) + else: + # TODO: return field name support + output_fields = fields_for_form(form, only_fields, exclude_fields) + + return_field_name = 'TODOFROMForm' if not return_field_name else return_field_name + output_fields['errors'] = graphene.Field(cls.Errors, required=True) - _meta = DjangoFormMutationOptions(cls) + _meta.return_field_name = return_field_name _meta.form_class = form_class _meta.fields = yank_fields_from_attrs(output_fields, _as=Field) @@ -128,76 +161,6 @@ class DjangoFormMutation(BaseDjangoFormMutation): _meta=_meta, input_fields=input_fields, **options ) - @classmethod - def perform_mutate(cls, form, info): - form.save() - return cls(errors=[]) - - -class DjangoModelDjangoFormMutationOptions(DjangoFormMutationOptions): - model = None - return_field_name = None - - -class DjangoModelFormMutation(BaseDjangoFormMutation): - class Meta: - abstract = True - - @classmethod - def __init_subclass_with_meta__( - cls, - form_class=None, - model=None, - return_field_name=None, - only_fields=(), - exclude_fields=(), - **options - ): - - if not form_class: - raise Exception("form_class is required for DjangoModelFormMutation") - - if not model: - model = form_class._meta.model - - if not model: - raise Exception("model is required for DjangoModelFormMutation") - - form = form_class() - input_fields = fields_for_form(form, only_fields, exclude_fields) - if "id" not in exclude_fields: - input_fields["id"] = graphene.ID() - - registry = get_global_registry() - model_type = registry.get_type_for_model(model) - return_field_name = return_field_name - if not return_field_name: - model_name = model.__name__ - return_field_name = model_name[:1].lower() + model_name[1:] - - output_fields = OrderedDict() - output_fields[return_field_name] = graphene.Field(model_type) - input_fields = yank_fields_from_attrs(input_fields, _as=InputField) - - base_name = cls.__name__ - - cls.Errors = create_errors_type( - "{}Errors".format(base_name), - input_fields - ) - - output_fields['errors'] = graphene.Field(cls.Errors, required=True) - - _meta = DjangoModelDjangoFormMutationOptions(cls) - _meta.form_class = form_class - _meta.model = model - _meta.return_field_name = return_field_name - _meta.fields = yank_fields_from_attrs(output_fields, _as=Field) - - super(DjangoModelFormMutation, cls).__init_subclass_with_meta__( - _meta=_meta, input_fields=input_fields, **options - ) - @classmethod def perform_mutate(cls, form, info): obj = form.save() diff --git a/graphene_django/forms/tests/test_mutation.py b/graphene_django/forms/tests/test_mutation.py index 14d03c4..2595cf0 100644 --- a/graphene_django/forms/tests/test_mutation.py +++ b/graphene_django/forms/tests/test_mutation.py @@ -6,7 +6,7 @@ from django.test import TestCase from graphene import NonNull, List from graphene_django.tests.models import Pet, Film, FilmDetails -from ..mutation import DjangoFormMutation, DjangoModelFormMutation +from ..mutation import DjangoFormMutation class MyForm(forms.Form): @@ -19,6 +19,12 @@ class PetForm(forms.ModelForm): fields = '__all__' +class FilmDetailsForm(forms.ModelForm): + class Meta: + model = FilmDetails + fields = '__all__' + + def test_needs_form_class(): with pytest.raises(Exception) as exc: class MyMutation(DjangoFormMutation): @@ -44,7 +50,7 @@ def test_has_input_fields(): def test_default_meta_fields(): - class PetMutation(DjangoModelFormMutation): + class PetMutation(DjangoFormMutation): class Meta: form_class = PetForm @@ -55,7 +61,7 @@ def test_default_meta_fields(): def test_default_input_meta_fields(): - class PetMutation(DjangoModelFormMutation): + class PetMutation(DjangoFormMutation): class Meta: form_class = PetForm @@ -68,7 +74,7 @@ def test_default_input_meta_fields(): def test_exclude_fields_input_meta_fields(): - class PetMutation(DjangoModelFormMutation): + class PetMutation(DjangoFormMutation): class Meta: form_class = PetForm exclude_fields = ['id'] @@ -82,30 +88,28 @@ def test_exclude_fields_input_meta_fields(): def test_return_field_name_is_camelcased(): - class PetMutation(DjangoModelFormMutation): + class FilmDetailsMutation(DjangoFormMutation): class Meta: - form_class = PetForm - model = FilmDetails + form_class = FilmDetailsForm - assert PetMutation._meta.model == FilmDetails - assert PetMutation._meta.return_field_name == "filmDetails" + assert FilmDetailsMutation._meta.model == FilmDetails + assert FilmDetailsMutation._meta.return_field_name == "filmDetails" -def test_custom_return_field_name(): - class PetMutation(DjangoModelFormMutation): +def test_custom_return_field_name_model_form(): + class FilmDetailsMutation(DjangoFormMutation): class Meta: - form_class = PetForm - model = Film - return_field_name = "animal" + form_class = FilmDetailsForm + return_field_name = "movie" - assert PetMutation._meta.model == Film - assert PetMutation._meta.return_field_name == "animal" - assert "animal" in PetMutation._meta.fields + assert FilmDetailsMutation._meta.model == FilmDetails + assert FilmDetailsMutation._meta.return_field_name == "movie" + assert "movie" in FilmDetailsMutation._meta.fields @pytest.mark.django_db def test_model_form_mutation_mutate(): - class PetMutation(DjangoModelFormMutation): + class PetMutation(DjangoFormMutation): class Meta: form_class = PetForm @@ -121,7 +125,7 @@ def test_model_form_mutation_mutate(): @pytest.mark.django_db def test_model_form_mutation_updates_existing(): - class PetMutation(DjangoModelFormMutation): + class PetMutation(DjangoFormMutation): class Meta: form_class = PetForm @@ -136,7 +140,7 @@ def test_model_form_mutation_updates_existing(): @pytest.mark.django_db def test_model_form_mutation_mutate_invalid_form(): - class PetMutation(DjangoModelFormMutation): + class PetMutation(DjangoFormMutation): class Meta: form_class = PetForm