mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-07-13 17:52:19 +03:00
Unify support for models and model form
This commit is contained in:
parent
19fcc3cdf2
commit
9aeee283fa
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user