Reputation: 6363
I am building a GraphQL API using the python packages Flask, SQLAlchemy, Graphene and Graphene-SQLAlchemy. I have followed the SQLAlchemy + Flask Tutorial. I am able to execute mutations to create records and I would like to get the global Id of this record in the response from the API:
Here are the classes implemented for the mutation:
from graphql_relay.node.node import to_global_id
import api_utils # Custom methods to create records in database
import batch_schema
import graphene
class CreateBatchOwnerInput(graphene.InputObjectType):
"""Input to create batch owner."""
name = graphene.String(required=True)
class CreateBatchOwner(graphene.Mutation):
"""Create batch owner."""
class Arguments:
input = CreateBatchOwnerInput(required=True)
# Class attributes
batch_owner = graphene.Field(batch_schema.BatchOwner)
@staticmethod
def mutate(root, info, input=None):
"""Method to create batch owner."""
record = {'name': input.name}
batch_owner = api_utils.create('BatchOwner', record) # This returns a dictionary {'id': int, 'name': string}
batch_owner = batch_schema.BatchOwner(**batch_owner)
batch_owner.id = to_global_id('BatchOwner', batch_owner.id) # Convert database Id to global Id
return CreateBatchOwner(batch_owner=batch_owner)
The following mutation works fine
mutation Mutation {
createBatchOwner(input: {name:"Jake"}) {
batchOwner {
name
}
}
}
response:
{
"data": {
"createBatchOwner": {
"batchOwner": {
"name": "Jake"
}
}
}
}
But when I add the "id" field in the payload I get the following error message:
mutation Mutation {
createBatchOwner(input: {name:"Antoine"}) {
batchOwner {
id
name
}
}
}
response:
{
"data": {
"createBatchOwner": {
"batchOwner": null
}
},
"errors": [
{
"message": "'BatchOwner' object has no attribute '__mapper__'",
"locations": [
{
"column": 11,
"line": 4
}
]
}
]
}
Here is the log generated by the Flask application:
Traceback (most recent call last):
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 311, in resolve_or_error
return executor.execute(resolve_fn, source, info, **args)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executors/sync.py", line 7, in execute
return fn(*args, **kwargs)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphene/relay/node.py", line 38, in id_resolver
type_id = parent_resolver(root, info, **args)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphene_sqlalchemy/types.py", line 160, in resolve_id
keys = self.__mapper__.primary_key_from_instance(self)
AttributeError: 'BatchOwner' object has no attribute '__mapper__'
Traceback (most recent call last):
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 330, in complete_value_catching_error
exe_context, return_type, field_asts, info, result)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 405, in complete_value
return complete_object_value(exe_context, return_type, field_asts, info, result)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 504, in complete_object_value
return execute_fields(exe_context, return_type, result, subfield_asts)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 148, in execute_fields
source_value, field_asts)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 247, in resolve_field
result
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 324, in complete_value_catching_error
return complete_value(exe_context, return_type, field_asts, info, result)
File "/home/alexis/data-quality-venv/lib/python3.5/site-packages/graphql/execution/executor.py", line 383, in complete_value
raise GraphQLLocatedError(field_asts, original_error=result)
graphql.error.located_error.GraphQLLocatedError: 'BatchOwner' object has no attribute '__mapper__'
Upvotes: 1
Views: 1355
Reputation: 647
The exact answer is id
reserved for graphene and never use it in any of your models although they have used it in their tutorial
Upvotes: 1
Reputation: 6363
I have solved the issue and documented it here in a tutorial.
Flask-Graphene-SQLAlchemy Tutorial
It seems both my mutate method and the definition of my SQLAlchemy class were incorrectly defined.
Upvotes: 1