Skip to content

stratosgear/graphene-mongo

 
 

Repository files navigation

GrapheneMongo

GrapheneMongo is a library that integrates Graphene with MongoeEngine   Build Status Coverage Status


Examples

Given that mongoengine Document:

class User(Document):
    username = StringField()
    creation_date = DateTimeField()
    favourite_color = ListField(StringField())

To generage a graphene schema for that Document we create a class that is subclass of graphene_mongo.MongoSchema, or we can also just call it passing the model as first argument:

from graphene_mongo import MongoSchema

class UserSchema(MongoSchema):
    model = User
# OR
UserSchema = MongoSchema(User)

The schema now it's generated. Now it's necessary to create a graphene object Query:

import graphene

class Query(graphene.ObjectType):
    user = UserSchema.single
    
schema = graphene.Schema(query=Query)

# now we can do the query:
result = schema.execute("""
query Data {
  user(username: "John") {
    id
    username
  }
}""")

You may notice the UserSchema.single atribute in the example above, the class UserSchema has many other atrributes. All they are explained below:

Atribute Description
single We use single we want that the query result be a unique result. That's the same that make the query in mongoengine calling .first() to get the first object that matchs the query.
list List is used when we want a list of the documents that matchs the query.
model That's easy, this attribute stores the original Document of mongoengine that you created.
fields This field is more consult, you can use the fields that was converted from mongoengine to graphene. For instance, in our UserSchema class the attribute field will be a dict like this: {'username': graphene.String}
mutation Mutate is the atribute that we use when creating Mutations with graphene. See more in Mutations

Mutations

Somethimes we need to save new data in the mongodb instead of doing querys. Mutation that do that job. Lets use again the UserSchema that we created in the examples. As before we created a graphene object called Query to handle the query, we now need to do the same to Mutation:

class Mutation(graphene.ObjectType):
    create_user = UserSchema.mutate

schema = graphene.Schema(query=Query, mutation=Mutation)

Notice that we updated the variable schema to has the mutation object too. Now we can do the mutation query and create a new user in our database:

result = schema.execute("""
mutation testMutation {
  createUser(username:"John") {
    person {
      id
      username
    }
  }
}""")

We pass pass the attributes that we want to save in the 'params', as wee did in "...createPerson(username:"John")..."

In this example graphene-mongo handled the save of the object to you, but somethimes you need to make validations before actualy save the object in to database. How you can do that is explain next.

Verifications before save

To use your own function to save you need to create a function in the MongoSchema class called mutate. Said that, lets update our UserSchema as follows:

class UserSchema(MongoSchema):
    model = User

    @staticmethod
    def mutate(args, context):
    	new_user = User(**args)
        new_user.creation_date = datetime.now()
        new_user.save()
        return new_user

There's not many rules here, you only need to be sure that the method receive two parameters, has the the staticmethod decorator and returns the instance of the object.

The context parameter has the request object of the framework that you're using. If you're using flask for instance, that parameter will be the flask global request.

Operators in query

Mongoengine offer many kinds of operators to use as 'in', 'gte', etc. See all operators in mongoengine documentation. With Graphene-mongo you can use they in your query:

result = schema.execute("""
query Data {
  user(username_Icontains: "John", creationDate_Gte:"1997-04-28", favouriteColor_In:["red"]) {
    id
    username
  }
}""")

The best is that they are all supported by graphene-mongo.

Validate permissions to do querys and mutations

To validate if a user can access some field you can create an atribute called validator:

class UserSchema(MongoSchema):
    model = User

    def validator(model, fields, query, special_params):
    	if 'not_alowed_field' in fields:
        	raise Exception('Unauthorized Access')

When a validator function exists, GrapheneMongo will call it in every query or mutation of the respective schema. Just be sure to raise a excelption that graphene will be responsible to send it back to graphql client in front.



TODOs

  • Accept user mutation return None;
  • Support ReferenceField of 'self' without raises 'maximum recursion' error.

About

Implementation of Graphene and Mongoengine

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%