Python-Graphene gae 0.1.7: GraphQL Support for Google AppEngine

icon
Latest Release: 0.1.7

0.1.7 (2016-06-14)

  • BREAKING: Fixed behavior of KeyProperty to expose GraphQL Global IDs instead of internal ndb.Key values. (PR #16)
Source code(tar.gz)
Source code(zip)
graphene_gae-0.1.7.tar.gz(23.41 KB)

Graphene GAE

https://travis-ci.org/graphql-python/graphene-gae.svg?branch=master https://coveralls.io/repos/github/graphql-python/graphene-gae/badge.svg?branch=master

A Google AppEngine integration library for Graphene

Upgrade Notes

If you're upgrading from an older version (pre 2.0 version) please check out the Graphene Upgrade Guide.

Installation

To install Graphene-GAE on your AppEngine project, go to your project folder and runthis command in your shell:

pip install graphene-gae -t ./libs

This will install the library and its dependencies to the libs folder under your projects root - so the dependencies get uploaded withyour GAE project when you publish your app.

Make sure the libs folder is in your python path by adding the following to your appengine_config.py:

import sys

for path in ['libs']:
    if path not in sys.path:
        sys.path[0:0] = [path]

Examples

Here's a simple GAE model:

class Article(ndb.Model):
    headline = ndb.StringProperty()
    summary = ndb.TextProperty()
    text = ndb.TextProperty()

    author_key = ndb.KeyProperty(kind='Author')

    created_at = ndb.DateTimeProperty(auto_now_add=True)
    updated_at = ndb.DateTimeProperty(auto_now=True)

To create a GraphQL schema for it you simply have to write the following:

import graphene
from graphene_gae import NdbObjectType

class ArticleType(NdbObjectType):
    class Meta:
        model = Article

class Query(graphene.ObjectType):
    articles = graphene.List(ArticleType)

    @graphene.resolve_only_args
    def resolve_articles(self):
        return Article.query()

schema = graphene.Schema(query=QueryRoot)

Then you can simply query the schema:

To learn more check out the following examples:

Contributing

After cloning this repo, ensure dependencies are installed by running:

make deps
make install

Make sure tests and lint are running:

make test
make lint

Comments

  • GraphiQL Integration for Webapp2
    GraphiQL Integration for Webapp2

    Aug 31, 2016

    Are there any guidelines for integrating GraphiQL here? I saw the Django integration, but it seems a bit different.

    Reply
  • Docs page does not exist
    Docs page does not exist

    Sep 30, 2016

    Maybe the links should be removed until the docs are ready.

    image

    bug 
    Reply
  • Passing query as JSON (for variables, etc.) seems broken
    Passing query as JSON (for variables, etc.) seems broken

    Oct 27, 2016

    I'm very new to this GraphQL world but my understanding of GraphQL is that, in order to pass variables or operation_name in addition to query, the body of POST has to be encoded in JSON. A GraphQL query HTML body, with a pair of query and variables, would look like:

    { "query": "...", "variables": "..." }
    

    This does not seem to work with graphene-gae. I put many logging.warn()'s in _get_grapl_params() but could not understand the intent. If the said assumption that GraphQL query body is either raw GraphQL or JSON, this _get_grapl_params() would look like:

        def _get_grapl_params(self):
            try:
                (read body as JSON)
            except:
                (read body as raw GraphQL)
    

    (I even have no idea why this handler has to be implemented in graphene-gae, not graphene.)

    I'm trying to fix this myself, but I'm slow; new to Python, new to GraphQL, new to Web world. Feel free to beat me. ;)

    Reply
  • Create README.rst
    Create README.rst

    Jun 14, 2017

                                                                                                                                                                                                           
    Reply
  • app.yaml handlers?
    app.yaml handlers?

    Aug 6, 2018

    I'm pretty new to Google App Engine.

    What do I need to add to the handlers section of app.yaml to make it work?

    Reply
  • GraphQL Integration for Cloud Endpoints
    GraphQL Integration for Cloud Endpoints

    Aug 16, 2018

    Is it possible to setup graphiql and / or graphql with cloud endpoints?

    Reply
  • Is it possible to use google-cloud-ndb with this package?
    Is it possible to use google-cloud-ndb with this package?

    Jan 27, 2020

    I know this package supports ndb w/ AppEngine. However, wondering if we could use graphene to support ndb from google-cloud-ndb?

    The difference i've seen so far between the two is google-cloud-ndb requries a client.context() for each query and mutation

    Reply
  • ndb.GeoPtProperty support
    ndb.GeoPtProperty support

    Feb 21, 2020

    ndb.GeoPtProperty is currently not supported as part of the converter.

    Reply
  • Looking for maintainers!
    Looking for maintainers!

    Aug 6, 2020

                                                                                                                                                                                                           
    Reply
  • Bump pyyaml from 3.11 to 5.4
    Bump pyyaml from 3.11 to 5.4

    Mar 25, 2021

    Bumps pyyaml from 3.11 to 5.4.

    Changelog

    Sourced from pyyaml's changelog.

    5.4 (2021-01-19)

    5.3.1 (2020-03-18)

    • yaml/pyyaml#386 -- Prevents arbitrary code execution during python/object/new constructor

    5.3 (2020-01-06)

    5.2 (2019-12-02)

    • Repair incompatibilities introduced with 5.1. The default Loader was changed, but several methods like add_constructor still used the old default yaml/pyyaml#279 -- A more flexible fix for custom tag constructors yaml/pyyaml#287 -- Change default loader for yaml.add_constructor yaml/pyyaml#305 -- Change default loader for add_implicit_resolver, add_path_resolver
    • Make FullLoader safer by removing python/object/apply from the default FullLoader yaml/pyyaml#347 -- Move constructor for object/apply to UnsafeConstructor
    • Fix bug introduced in 5.1 where quoting went wrong on systems with sys.maxunicode <= 0xffff yaml/pyyaml#276 -- Fix logic for quoting special characters
    • Other PRs: yaml/pyyaml#280 -- Update CHANGES for 5.1

    5.1.2 (2019-07-30)

    • Re-release of 5.1 with regenerated Cython sources to build properly for Python 3.8b2+

    ... (truncated)

    Commits
    • 58d0cb7 5.4 release
    • a60f7a1 Fix compatibility with Jython
    • ee98abd Run CI on PR base branch changes
    • ddf2033 constructor.timezone: _copy & deepcopy
    • fc914d5 Avoid repeatedly appending to yaml_implicit_resolvers
    • a001f27 Fix for CVE-2020-14343
    • fe15062 Add 3.9 to appveyor file for completeness sake
    • 1e1c7fb Add a newline character to end of pyproject.toml
    • 0b6b7d6 Start sentences and phrases for capital letters
    • c976915 Shell code improvements
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Support for mapping\filtering entities in ndb connection field
    Support for mapping\filtering entities in ndb connection field

    Nov 22, 2016

    This PR contains support for post NDB query interference to achieve mapping and filtering of entities fetched by NDB queries resolved within NDBConnectionFields.

    It's very useful in situations where there's a many to many relation between two NDB models and you need to paginate over them. See the added tests for an example.

    Example explained - A new Reader model was added. Each reader may have read multiple articles, and each article may have been read by multiple readers. The many to many relation is implemented using the ArticleReader model which represents that some reader has read an article and contains the reader key and article key. Now, in order to paginate over all the article readers, the readers property was added to ArticleType: readers = NdbConnectionField(ReaderType, entities_mapper=readers_mapper, entity_filter=reader_filter) Notice that ArticleType's resolve_readers returns a query for all the ArticleReader entities. Upon resolving it readers_mapper is called and maps each article reader to the appropriate reader. Later we filter the readers in reader_filter and only return the readers that are alive.

    Reply
  • If transform_edges filtered some edges continue generating edges to reach page size
    If transform_edges filtered some edges continue generating edges to reach page size

    Nov 23, 2016

    NDBConnectionfield now continues generating edges until it reaches the requested page size. Even if transform_edges filters several edges in the process.

    Reply
  • TimeProperty
    TimeProperty

    Sep 26, 2017

    NDB has support for TimeProperty but it seems to be missing.

    In https://github.com/graphql-python/graphene-gae/blob/master/graphene_gae/ndb/converter.py#L129 I see:

    converters = {
        ndb.StringProperty: convert_ndb_string_property,
        ndb.TextProperty: convert_ndb_string_property,
        ndb.BooleanProperty: convert_ndb_boolean_property,
        ndb.IntegerProperty: convert_ndb_int_property,
        ndb.FloatProperty: convert_ndb_float_property,
        ndb.JsonProperty: convert_ndb_json_property,
        ndb.DateProperty: convert_ndb_datetime_property,
        ndb.DateTimeProperty: convert_ndb_datetime_property,
        ndb.KeyProperty: convert_ndb_key_propety,
        ndb.StructuredProperty: convert_local_structured_property,
        ndb.LocalStructuredProperty: convert_local_structured_property,
        ndb.ComputedProperty: convert_computed_property
    }
    

    Is it as simple as just adding ndb.TimeProperty: convert_ndb_datetime_property?

    Reply
  • Expected value of type
    Expected value of type "UserType" but got: User

    Jan 17, 2018

    Hi,

    I try to develop simple GraphQL with graphene-gae using flask framework. But I'm getting error when I try to execute the query. The query is:

    query {
        allUsers {
            username,
            email
        }
    }
    

    and the error message is Expected value of type \"UserType\" but got: User

    Here is my snippet of code

    user.py

    from google.appengine.ext import ndb
    
    
    class User(ndb.Model):
        username = ndb.StringProperty()
        email = ndb.StringProperty()
        password = ndb.StringProperty()
        created_at = ndb.DateTimeProperty(auto_now_add=True)
        updated_at = ndb.DateTimeProperty(auto_now=True)
    

    schema.py

    import graphene
    
    from graphene_gae import NdbObjectType
    from user import User
    
    
    class UserType(NdbObjectType):
        class Meta:
            model = User
    
    
    class Query(graphene.ObjectType):
        all_users = graphene.List(UserType)
    
        def resolve_all_users(self, info):
            return User.query()
    
    
    schema = graphene.Schema(query=Query)
    

    I'm using graphene-gae 2.0.dev2017073101

    Reply
  • Improved conversion of ndb.KeyProperty to GraphQL
    Improved conversion of ndb.KeyProperty to GraphQL

    Jun 8, 2016

    Basically we want to allow 2 ways of accessing a key's values.

    1. Access the key's actual value without querying NDB - we'll just use key.urlsafe()
    2. Resolve the key to an entity and query that entity - key.get()

    We support 2 naming conventions:

    _key or _keys Suffix

    NDB Model has a property that looks like this: store_key = ndb.KeyProperty(...) In this case we'll convert it into the following 2 GraphQL fields:

    store_key = graphene.String()  # resolves to entity.store_key.urlsafe()
    store = NdbKeyField()  # resolves to entity entity.store_key.get()
    

    Regular Name

    NDB Model has a property that looks like this: store = ndb.KeyProperty(...) In this case we'll convert it into the following 2 GraphQL fields:

    store_key = graphene.String() -> resolves to store_key.urlsafe()
    store     = NdbKeyField()     -> resolves to entity
    
    Reply
  • Expose NDB id in models
    Expose NDB id in models

    Aug 16, 2016

                                                                                                                                                                                                           
    Reply
  • Fix for PolyModel type lookup
    Fix for PolyModel type lookup

    Sep 24, 2018

    Note: When using graphene Interfaces, previous implementation could display false positives by only checking if the root type matches with the given model. Now if you pass in an Interface type, the check will check that the object type's class hierarchy is a subset of the instance's class hierarchy

    Reply
  • GraphQLHandler: GET requests
    GraphQLHandler: GET requests

    Feb 9, 2017

    Hello! Since handling query parameters is already done for POST requests in GraphQLHandler, it seems like we could trivially do GET requests. So, here that is!

    I've augmented all relevant tests to test GET as well as POST.

    I'm new to GraphQL but it seems kinda funny to accept mutations via an HTTP GET?

    Reply
  • Implement query handler
    Implement query handler

    May 26, 2016

    Implement a base handler that can handle GraphQL queries and mutations. Inspired by https://github.com/graphql-python/graphql-django-view

    • [x] Base GoogleAppengine webapp2 handler that answers GraphQL queries

    Example - sample app (cookbook?) to also use in the http://graphene-python.org/ docs - move to separate branch

    Work In Progress 
    Reply
  • Adapt code to Graphene 2.0
    Adapt code to Graphene 2.0

    Jul 27, 2017

    Adapt code to Graphene 2.0

    Related PR: https://github.com/graphql-python/graphene/pull/500

    Reply