From 5aafca90dc57b12ec2334a9a0d17833a34f8aa03 Mon Sep 17 00:00:00 2001 From: Samuele Santi Date: Wed, 25 Jul 2018 13:15:47 +0100 Subject: [PATCH] Remove flask_graphql.fields, add docs to README --- README.md | 98 +++++++++++++++++++++++++++++++++++++++++ flask_graphql/fields.py | 45 ------------------- tests/schema.py | 10 ++++- 3 files changed, 106 insertions(+), 47 deletions(-) delete mode 100644 flask_graphql/fields.py diff --git a/README.md b/README.md index 8c918ae..660acea 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,101 @@ class UserRootValue(GraphQLView): return request.user ``` + +### File upload support + +File uploads are supported via [multipart requests](https://github.com/jaydenseric/graphql-multipart-request-spec). + +You can simply define a ``FileUpload`` field in your schema, and use +it to receive data from uploaded files. + + +Example using ``graphql-core``: + +```python +from collections import NamedTuple +from graphql.type.definition import GraphQLScalarType + + +GraphQLFileUpload = GraphQLScalarType( + name='FileUpload', + description='File upload', + serialize=lambda x: None, + parse_value=lambda value: value, + parse_literal=lambda node: None, +) + + +FileEchoResult = namedtuple('FileEchoResult', 'data,name,type') + + +FileEchoResultSchema = GraphQLObjectType( + name='FileEchoResult, + fields={ + 'data': GraphQLField(GraphQLString), + 'name': GraphQLField(GraphQLString), + 'type': GraphQLField(GraphQLString), + } +) + + +def resolve_file_echo(obj, info, file): + data = file.stream.read().decode() + return FileEchoResult( + data=data, + name=file.filename, + type=file.content_type) + + +MutationRootType = GraphQLObjectType( + name='MutationRoot', + fields={ + # ... + 'fileEcho': GraphQLField( + type=FileUploadTestResultSchema, + args={'file': GraphQLArgument(GraphQLFileUpload)}, + resolver=resolve_file_echo, + ), + # ... + } +) +``` + + +Example using ``graphene``: + +```python +import graphene + +class FileUpload(graphene.Scalar): + + @staticmethod + def serialize(value): + return None + + @staticmethod + def parse_literal(node): + return None + + @staticmethod + def parse_value(value): + return value # IMPORTANT + + +class FileEcho(graphene.Mutation): + + class Arguments: + myfile = FileUpload(required=True) + + ok = graphene.Boolean() + name = graphene.String() + data = graphene.String() + type = graphene.String() + + def mutate(self, info, myfile): + return FileEcho( + ok=True + name=myfile.filename + data=myfile.stream.read(), + type=myfile.content_type) +``` diff --git a/flask_graphql/fields.py b/flask_graphql/fields.py deleted file mode 100644 index bebbcf5..0000000 --- a/flask_graphql/fields.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Provide field definitions for file uploads - -TODO: this should be supported upstream, in graphql-core -and graphene. Shall we just remove it from here and only -provide a reference definition instead? -""" - -try: - from graphql.type.definition import GraphQLScalarType - -except ImportError: - pass - -else: - - GraphQLFileUpload = GraphQLScalarType( - name='FileUpload', - description='File upload', - serialize=lambda x: None, - parse_value=lambda value: value, - parse_literal=lambda node: None, - ) - - -try: - import graphene - -except ImportError: - pass - -else: - - class FileUpload(graphene.Scalar): - - @staticmethod - def serialize(value): - return None - - @staticmethod - def parse_literal(node): - return None - - @staticmethod - def parse_value(value): - return value # IMPORTANT diff --git a/tests/schema.py b/tests/schema.py index 7b86329..893b7b1 100644 --- a/tests/schema.py +++ b/tests/schema.py @@ -4,8 +4,6 @@ from graphql.type.scalars import GraphQLString from graphql.type.schema import GraphQLSchema -from flask_graphql.fields import GraphQLFileUpload - def resolve_raises(*_): raise Exception("Throws!") @@ -39,6 +37,14 @@ def resolve_raises(*_): } ) +GraphQLFileUpload = GraphQLScalarType( + name='FileUpload', + description='File upload', + serialize=lambda x: None, + parse_value=lambda value: value, + parse_literal=lambda node: None, +) + def to_object(dct): class MyObject(object):