Skip to content

Nameko example - Pure API based example. #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@ class Query(graphene.ObjectType):
schema = graphene.Schema(query=Query)
```

To learn more check out the following [examples](examples/):
### Full Examples

* **Full example**: [Flask SQLAlchemy example](examples/flask_sqlalchemy)
To learn more check out the following [examples](examples/):

- [Flask SQLAlchemy example](examples/flask_sqlalchemy)
- [Nameko SQLAlchemy example](examples/nameko_sqlalchemy)

## Contributing

Expand Down
54 changes: 54 additions & 0 deletions examples/nameko_sqlalchemy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Example Nameko+Graphene-SQLAlchemy Project
================================

This example is for those who are not using frameworks like Flask | Django which already have a View wrapper implemented to handle graphql request and response accordingly

If you need a [graphiql](https://github.com/graphql/graphiql) interface on your application, kindly look at [flask_sqlalchemy](../flask_sqlalchemy).

Using [nameko](https://github.com/nameko/nameko) as an example, but you can get rid of `service.py`

The project contains two models, one named `Department` and another
named `Employee`.

Getting started
---------------

First you'll need to get the source of the project. Do this by cloning the
whole Graphene repository:

```bash
# Get the example project code
git clone https://github.com/graphql-python/graphene-sqlalchemy.git
cd graphene-sqlalchemy/examples/nameko_sqlalchemy
```

It is good idea (but not required) to create a virtual environment
for this project. We'll do this using
[virtualenv](http://docs.python-guide.org/en/latest/dev/virtualenvs/)
to keep things simple,
but you may also find something like
[virtualenvwrapper](https://virtualenvwrapper.readthedocs.org/en/latest/)
to be useful:

```bash
# Create a virtualenv in which we can install the dependencies
virtualenv env
source env/bin/activate
```

Now we can install our dependencies:

```bash
pip install -r requirements.txt
```

Now the following command will setup the database, and start the server:

```bash
./run.sh

```

Now head on over to postman and send POST request to:
[http://127.0.0.1:5000/graphql](http://127.0.0.1:5000/graphql)
and run some queries!
Empty file.
36 changes: 36 additions & 0 deletions examples/nameko_sqlalchemy/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from database import db_session, init_db
from schema import schema

from graphql_server import (HttpQueryError, default_format_error,
encode_execution_results, json_encode,load_json_body, run_http_query)


class App():
def __init__(self):
init_db()

def query(self, request):
data = self.parse_body(request)
execution_results, params = run_http_query(
schema,
'post',
data)
result, status_code = encode_execution_results(
execution_results,
format_error=default_format_error,is_batch=False, encode=json_encode)
return result

def parse_body(self,request):
# We use mimetype here since we don't need the other
# information provided by content_type
content_type = request.mimetype
if content_type == 'application/graphql':
return {'query': request.data.decode('utf8')}

elif content_type == 'application/json':
return load_json_body(request.data.decode('utf8'))

elif content_type in ('application/x-www-form-urlencoded', 'multipart/form-data'):
return request.form

return {}
1 change: 1 addition & 0 deletions examples/nameko_sqlalchemy/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
WEB_SERVER_ADDRESS: '0.0.0.0:5000'
38 changes: 38 additions & 0 deletions examples/nameko_sqlalchemy/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()


def init_db():
# import all modules here that might define models so that
# they will be registered properly on the metadata. Otherwise
# you will have to import them first before calling init_db()
from models import Department, Employee, Role
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)

# Create the fixtures
engineering = Department(name='Engineering')
db_session.add(engineering)
hr = Department(name='Human Resources')
db_session.add(hr)

manager = Role(name='manager')
db_session.add(manager)
engineer = Role(name='engineer')
db_session.add(engineer)

peter = Employee(name='Peter', department=engineering, role=engineer)
db_session.add(peter)
roy = Employee(name='Roy', department=engineering, role=engineer)
db_session.add(roy)
tracy = Employee(name='Tracy', department=hr, role=manager)
db_session.add(tracy)
db_session.commit()
39 changes: 39 additions & 0 deletions examples/nameko_sqlalchemy/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, func
from sqlalchemy.orm import backref, relationship

from database import Base


class Department(Base):
__tablename__ = 'department'
id = Column(Integer, primary_key=True)
name = Column(String)


class Role(Base):
__tablename__ = 'roles'
role_id = Column(Integer, primary_key=True)
name = Column(String)


class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
name = Column(String)
# Use default=func.now() to set the default hiring time
# of an Employee to be the current time when an
# Employee record was created
hired_on = Column(DateTime, default=func.now())
department_id = Column(Integer, ForeignKey('department.id'))
role_id = Column(Integer, ForeignKey('roles.role_id'))
# Use cascade='delete,all' to propagate the deletion of a Department onto its Employees
department = relationship(
Department,
backref=backref('employees',
uselist=True,
cascade='delete,all'))
role = relationship(
Role,
backref=backref('roles',
uselist=True,
cascade='delete,all'))
4 changes: 4 additions & 0 deletions examples/nameko_sqlalchemy/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
graphene[sqlalchemy]
SQLAlchemy==1.0.11
nameko
graphql-server-core
4 changes: 4 additions & 0 deletions examples/nameko_sqlalchemy/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
echo "Starting application service server"
# Run Service
nameko run --config config.yml service
37 changes: 37 additions & 0 deletions examples/nameko_sqlalchemy/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import graphene
from graphene import relay
from graphene_sqlalchemy import SQLAlchemyConnectionField, SQLAlchemyObjectType
from models import Department as DepartmentModel
from models import Employee as EmployeeModel
from models import Role as RoleModel


class Department(SQLAlchemyObjectType):

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


class Employee(SQLAlchemyObjectType):

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


class Role(SQLAlchemyObjectType):

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


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


schema = graphene.Schema(query=Query, types=[Department, Employee, Role])
11 changes: 11 additions & 0 deletions examples/nameko_sqlalchemy/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env python
from nameko.web.handlers import http
from app import App


class DepartmentService:
name = 'department'

@http('POST', '/graphql')
def query(self, request):
return App().query(request)