graphene-sqlalchemy icon indicating copy to clipboard operation
graphene-sqlalchemy copied to clipboard

Question about querying a single resource with flask sqlalchemy example.

Open mojochao opened this issue 7 years ago • 7 comments

I have followed the example at http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tutorial/#testing-our-graphql-schema and have a question.

I can issue the following query to list all employees and their departments.

{
  allEmployees {
    edges {
      node {
        name
        department {
          name
        }
      }
    }
  }
}

I would like to be able to query a single employee name and their department name by employee id. I can query using the Node interface, but that doesn't allow me to access Employee name field. Am I supposed to "cast" this to the specific Employee type to do that? What I would like is something like:

{
  employee(id: "someid") {
    name
    department {
      name
    }
}

Is this reasonable or am I "doing it wrong"? What is best practice for accessing a single employee using the Relay connections/nodes/edges paradigm?

Many thanks in advance!

mojochao avatar Aug 23 '17 18:08 mojochao

Just add it to your Query class:

class Query(graphene.ObjectType):
    node = relay.Node.Field()
    all_employees = SQLAlchemyConnectionField(Employee)
    employee = relay.Node.Field(Employee)

nmrtv avatar Aug 24 '17 02:08 nmrtv

That did the trick. Thanks so much for the pointers!

mojochao avatar Aug 28 '17 00:08 mojochao

@mojochao @neriusmika What if you need to find by Employee name or any other field ? How do we expose that, Could not find an example here on querying by any other field.

kavink avatar Nov 05 '17 00:11 kavink

You could do something like this.

find_employee = graphene.Field(lambda: Employee, name=graphene.String())

def resolve_find_employee(self, args, context, info):
    query = Employee.get_query(context)
    name = args.get('name')
    return query.filter(EmployeeModel.name == name).first()

navinesh avatar Nov 14 '17 01:11 navinesh

Anyone know how its possible to do custom resolve methods on a single item?

import graphene
from .Model import Client
from graphene_sqlalchemy import SQLAlchemyConnectionField
from app.schema.authorizers import login_req

class Query(graphene.ObjectType):
    clients = SQLAlchemyConnectionField(Client)
    client = graphene.relay.Node.Field(Client)

    def resolve_clients(self, info, **kwargs):
        query = Client.get_query(info)
        return query.all()

    @login_req
    def resolve_client(self,info):
        # stuff?
        pass

It seems that resolve_SINGLERELAYITEM isn't looking to the query resolve method?

jrazmi avatar Jan 09 '18 02:01 jrazmi

You could do something like this.

find_employee = graphene.Field(lambda: Employee, name=graphene.String())

def resolve_find_employee(self, args, context, info):
    query = Employee.get_query(context)
    name = args.get('name')
    return query.filter(EmployeeModel.name == name).first()

Thanks for the pointers @navinesh. This worked great:

class Query(graphene.ObjectType):
    ...
    find_employee = graphene.Field(lambda: Employee, name=graphene.String())

    def resolve_find_employee(self, info, **kwargs):
        query = Employee.get_query(info)
        name = kwargs.get("name")
        return query.filter(EmployeeModel.name == name).first()
query FindEmployeeByName($name: String = "Tracy") {
    findEmployee(name: $name) {
        id
        name
        department {
            name
        }
    }
}

tlbjr avatar Jul 06 '19 21:07 tlbjr

Hi, I have a tag model and I would like to search for a specific tag with a specific name. Here is what I have , based on what was described above

from datetime import datetime
from graphene_sqlalchemy import SQLAlchemyObjectType,SQLAlchemyConnectionField
from database.base import db_session
from database.models.model_post import ModelPost
from database.models.model_image import ModelImage
from database.models.model_posttag  import PostsTags
from database.models.model_tag import ModelTag
from database.models.model_user import ModelUser
from database.models.model_locale import ModelLocale
import graphene
from helpers import utils


# Create a generic class to mutualize description of user attributes for both queries and mutations
class TagAttribute:
    name = graphene.String(description="Tag Name")
    isactive = graphene.Boolean(description="is active")


class Tag(SQLAlchemyObjectType):
    """Tag node."""

    class Meta:
        model = ModelTag
        interfaces = (graphene.relay.Node,)

class Query(graphene.ObjectType):
    tagToFind = graphene.Field(lambda: Tag, name=graphene.String())

    def resolve_find_tag(self, info, **kwargs):
        query = Tag.get_query(info)
        name = kwargs.get("name")
        return query.filter(TagModel.name == name).first()

class CreateTagInput(graphene.InputObjectType, TagAttribute):
    """Arguments to create a tag."""
    pass


class CreateTag(graphene.Mutation):
    """Mutation to create a tag."""
    tag = graphene.Field(lambda: Tag, description="tag created by this mutation.")

    class Arguments:
        input = CreateTagInput(required=True)

    def mutate(self, info, input):
        data = utils.input_to_dictionary(input)
        data['created_at'] = datetime.utcnow()
        data['updated_at'] = datetime.utcnow()

        tag = ModelTag(**data)
        db_session.add(tag)
        db_session.commit()

        return CreateTag(tag=tag)


class UpdateTagInput(graphene.InputObjectType, TagAttribute):
    """Arguments to update a tag."""
    id = graphene.ID(required=True, description="Global Id of the tag.")


class UpdateTag(graphene.Mutation):
    """Update a tag."""
    tag = graphene.Field(lambda: Tag, description="tag updated by this mutation.")

    class Arguments:
        input = UpdateTagInput(required=True)

    def mutate(self, info, input):
        data = utils.input_to_dictionary(input)
        data['updated_at'] = datetime.utcnow()

        tag = db_session.query(ModelTag).filter_by(id=data['id'])
        tag.update(data)
        db_session.commit()
        tag = db_session.query(ModelTag).filter_by(id=data['id']).first()

        return UpdateTag(tag=tag)

Here is a query that I have

query FindTagByName($name: String ="searchstring"){
  findTag(name: $name) {
    id
    name
  }
}

but I am getting this error

image

Can you please tell me what I am doing wrong here ? Thanks

gj1118 avatar Jul 26 '19 04:07 gj1118