Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
allen-munsch committed Jul 24, 2023
1 parent b1494da commit e3261fe
Showing 1 changed file with 55 additions and 13 deletions.
68 changes: 55 additions & 13 deletions graphene_django/rest_framework/mutation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from enum import Enum

from collections import OrderedDict

from django.shortcuts import get_object_or_404
from rest_framework import serializers

import graphene
from graphene.relay.mutation import ClientIDMutation
Expand All @@ -19,22 +22,37 @@ class SerializerMutationOptions(MutationOptions):
serializer_class = None


def fields_for_serializer(serializer, only_fields, exclude_fields, is_input=False):
def fields_for_serializer(
serializer,
only_fields,
exclude_fields,
is_input=False,
convert_choices_to_enum=True,
lookup_field=None,
):
fields = OrderedDict()
for name, field in serializer.fields.items():
is_not_in_only = only_fields and name not in only_fields
is_excluded = (
name
in exclude_fields # or
# name in already_created_fields
) or (
field.write_only and not is_input # don't show write_only fields in Query
is_excluded = any(
[
name in exclude_fields,
field.write_only
and not is_input, # don't show write_only fields in Query
field.read_only
and is_input
and lookup_field != name, # don't show read_only fields in Input
isinstance(
field, serializers.HiddenField
), # don't show hidden fields in Input
]
)

if is_not_in_only or is_excluded:
continue

fields[name] = convert_serializer_field(field, is_input=is_input)
fields[name] = convert_serializer_field(
field, is_input=is_input, convert_choices_to_enum=convert_choices_to_enum
)
return fields


Expand All @@ -55,6 +73,8 @@ def __init_subclass_with_meta__(
model_operations=("create", "update"),
only_fields=(),
exclude_fields=(),
convert_choices_to_enum=True,
_meta=None,
**options
):
if not serializer_class:
Expand All @@ -73,13 +93,24 @@ def __init_subclass_with_meta__(
lookup_field = model_class._meta.pk.name

input_fields = fields_for_serializer(
serializer, only_fields, exclude_fields, is_input=True
serializer,
only_fields,
exclude_fields,
is_input=True,
convert_choices_to_enum=convert_choices_to_enum,
lookup_field=lookup_field,
)
output_fields = fields_for_serializer(
serializer, only_fields, exclude_fields, is_input=False
serializer,
only_fields,
exclude_fields,
is_input=False,
convert_choices_to_enum=convert_choices_to_enum,
lookup_field=lookup_field,
)

_meta = SerializerMutationOptions(cls)
if not _meta:
_meta = SerializerMutationOptions(cls)
_meta.lookup_field = lookup_field
_meta.model_operations = model_operations
_meta.serializer_class = serializer_class
Expand All @@ -95,14 +126,21 @@ def __init_subclass_with_meta__(
def get_serializer_kwargs(cls, root, info, **input):
lookup_field = cls._meta.lookup_field
model_class = cls._meta.model_class

if model_class:
# check if input is Enum, and serialize value into input
for k, v in input.items():
attr = getattr(cls.Input, k)
type_ = getattr(attr, "type")
if isinstance(v, Enum) and type_.get(v.value):
input[k] = v.value
if "update" in cls._meta.model_operations and lookup_field in input:
instance = get_object_or_404(
model_class, **{lookup_field: input[lookup_field]}
)
partial = True
elif "create" in cls._meta.model_operations:
instance = None
partial = False
else:
raise Exception(
'Invalid update operation. Input parameter "{}" required.'.format(
Expand All @@ -114,6 +152,7 @@ def get_serializer_kwargs(cls, root, info, **input):
"instance": instance,
"data": input,
"context": {"request": info.context},
"partial": partial,
}

return {"data": input, "context": {"request": info.context}}
Expand All @@ -137,6 +176,9 @@ def perform_mutate(cls, serializer, info):
kwargs = {}
for f, field in serializer.fields.items():
if not field.write_only:
kwargs[f] = field.get_attribute(obj)
if isinstance(field, serializers.SerializerMethodField):
kwargs[f] = field.to_representation(obj)
else:
kwargs[f] = field.get_attribute(obj)

return cls(errors=None, **kwargs)

0 comments on commit e3261fe

Please sign in to comment.