Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Uploads when using Django Form #30

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions graphene_file_upload/django/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
"""Apply multipart request spec to django"""
import json
from django.forms import FileField
from graphene_django.views import GraphQLView
from graphene_django.forms.converter import convert_form_field

from ..utils import place_files_in_operations
from ..scalars import Upload


@convert_form_field.register(FileField)
def convert_form_field_to_upload(field):
return Upload(description=field.help_text, required=field.required)


class FileUploadGraphQLView(GraphQLView):
Expand Down
126 changes: 126 additions & 0 deletions graphene_file_upload/django/mutation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
from collections import OrderedDict
from django.forms import FileField
import graphene
from graphene import Field, InputField
from graphene.types.utils import yank_fields_from_attrs
from graphene_django.registry import get_global_registry
from graphene_django.forms.converter import convert_form_field
from graphene_django.forms.types import ErrorType
from graphene_django.forms.mutation import BaseDjangoFormMutation, DjangoModelDjangoFormMutationOptions


def fields_for_form(form, only_fields, exclude_fields):
fields = OrderedDict()
file_fields = []
for name, field in form.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
)

if is_not_in_only or is_excluded:
continue

if isinstance(field, FileField):
file_fields.append(name)

fields[name] = convert_form_field(field)
return (fields, file_fields)


class DjangoUploadModelDjangoFormMutationOptions(DjangoModelDjangoFormMutationOptions):
file_fields = None # type: array


class BaseDjangoUploadFormMutation(BaseDjangoFormMutation):
class Meta:
abstract = True

@classmethod
def get_form(cls, root, info, **input):
form_kwargs = {}
pk = input.pop("id", None)
if pk:
instance = cls._meta.model._default_manager.get(pk=pk)
form_kwargs["instance"] = instance

files_dict = OrderedDict()
for v in cls._meta.file_fields:
files_dict[v] = input.pop(v)
return cls._meta.form_class(input, files_dict, **form_kwargs)

@classmethod
def get_form_kwargs(cls, root, info, **input):
kwargs = {"data": input}

pk = input.pop("id", None)
if pk:
instance = cls._meta.model._default_manager.get(pk=pk)
kwargs["instance"] = instance

return kwargs


class DjangoUploadModelFormMutation(BaseDjangoUploadFormMutation):
class Meta:
abstract = True

errors = graphene.List(ErrorType)

@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, file_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)

_meta = DjangoUploadModelDjangoFormMutationOptions(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)
_meta.file_fields = file_fields

input_fields = yank_fields_from_attrs(input_fields, _as=InputField)

super(DjangoUploadModelFormMutation, cls).__init_subclass_with_meta__(
_meta=_meta, input_fields=input_fields, **options
)

@classmethod
def perform_mutate(cls, form, info):
obj = form.save()
kwargs = {cls._meta.return_field_name: obj}
return cls(errors=[], **kwargs)