Keith Yang, May 2018, PyCon



F&B POS
from future import __hope__At the point of sale, the merchant calculates the amount owed by the customer, indicates that amount, may prepare an invoice for the customer, which may be a cash register printout, and indicates the options for the customer to make payment. -- Point of Sale, Wikipedia

R&D Teams

/users vs /users//pos/client/API/ vs alias /api/v1/posGET, POST, PUT or ... PATCH?400, 403, 429 or ... 302?Disclaimer: not all caused by RESTful if carefully crafted with OpenAPI Specification (Swagger or Stoplight)
HTTP GET
/games/1
{
'status': 123,
'name': '🐲'
},
}


HTTP GET
/graphql?query={ restaurant(id: "1") \
{ name, category { primary } } }
{
'data': {
'category': {
'primary': 'Taiwanese Cuisine',
},
'name': 'Mazendo'
},
'errors': []
}
HTTP GET
/restaurants/1
{
'category': {
'primary': 'Taiwanese Cuisine',
'second': 'Beef Noodle',
},
'name': 'Mazendo'
},
}
GET requests, andPOST/PATCH/PUT/DELETE requestsGraphQL is a keyword easier to find IMMO.For example, between ECMAScript and Python

query {
restaurant {
logoUrl: String!
}
}
differenceAmount vs workingPricedefaultPrice vs startMoneyquery {
restaurant {
settings {
...
}
}
}
errors and data{
"errors": [{
"message": String,
...
}],
"data": {
"restaurant": {
"settings": {...}
}
}
}
Where it takes time to learn
Grow with spec evolving
interface Restaurant {
id: ID!
name: String!
categories: [Category]!
}
type TaiwaneseRestaurant implements Restaurant {
id: ID!
name: String!
categories: [Category]!
tax_unique_identifier: String
}
pip install grapheneMAKE LIVE EASIERimport graphene
...
class ReportObject(graphene.ObjectType):
timestamp = graphene.Int()
uuid = graphene.UUID()
type = InventoryTypeGrapheneEnum()
...
purchase_amount = graphene.String()
counting_amount = graphene.Float()
▾ graphene/
▸ pyutils/
▸ relay/
▾ test/
__init__.py
▾ tests/
▸ issues/
__init__.py
▸ types/
▸ utils/
__init__.py
LICENSE
MANIFEST.in
mypy.ini
README.rst
setup.cfg
setup.py
...
UPGRADE-v2.0.md
▸ bin/
▸ docs/
▸ examples/

!=
apollographql/graphql-toolsLooks fine to be with graphene-django

cookbook/urls.py
from django.conf.urls import url
from django.contrib import admin
from graphene_django.views import GraphQLView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql', GraphQLView.as_view(graphiql=True)),
]
cookbook/recipes/schema.py
from cookbook.recipes.models import Recipe, RecipeIngredient
from graphene import Node
from graphene_django.types import DjangoObjectType
class RecipeNode(DjangoObjectType):
class Meta:
model = Recipe
interfaces = (Node, )
filter_fields = ['title','amounts']
cookbook/recipes/schema.py
from graphene_django.filter import DjangoFilterConnectionField
class Query(object):
recipe = Node.Field(RecipeNode)
all_recipes = DjangoFilterConnectionField(RecipeNode)
recipeingredient = Node.Field(RecipeIngredientNode)
all_recipeingredients = DjangoFilterConnectionField(
RecipeIngredientNode)
It does provide SerializerMutation to help you with DRF. However in our case
from graphene_django.rest_framework.mutation import \
SerializerMutation
class MyAwesomeMutation(SerializerMutation):
class Meta:
serializer_class = MySerializer
ichef/queryfilterTo share same query interface between Django ORM, SQLAlchemy, GraphQL backend, and raw dict
queryfilterdicts = [
{"age": None},
{"age": 1},
{"age": 2},
]
query_filter = QueryFilter({
"age": {
"type": "number",
"options": {"drop_none": True},
"min": 0, "max": 1,
}
})
assert len(query_filter.on_dicts(dicts)) == 1
queryfilterimport graphene
from queryfilter import (QueryFilter,
BirthFilterQueryType, TextFilterQueryType,
NumberRangeFilterQueryType)
class UserQueryFilter(graphene.InputObjectType):
name = TextFilterQueryType()
birth = BirthFilterQueryType()
total_login = NumberRangeFilterQueryType()
I’ve spent 2 years trying to get Apollo Server into prod,
now I’ll no doubt have to make changes.
r/graphql graphene-python/*Graphene-Mongo ichef/queryfilterJust like all other new or different technology you hope to have in the orgazination, it's more of team art and culture. Then it's not always someone's fault, in different condition it's just meant to be failed. It's just that if you didn't try, things surely won't happen. Sometimes it's just that the technology not worthy indead. For this one, I encourage you to try on.