You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Nov 16, 2018. It is now read-only.
Thank you @mbrochh for the introduction to the GraphQL stack at the Djangonauts meetup. Kudos to the well prepared presentation and sample codes.
I have a few thoughts and suggestions which I didn't raise during the meetup due to time constrain, hence I'm sharing it here for your consideration. (I'm relatively new to GraphQL so please take my words with a pinch of salt.)
Node
It may be worth mentioning that Node is part of the Facebook Relay specs (not GraphQL specs). However, most framework (Graphene included) implement this spec due to the close association between Relay and GraphQL.
Essentially Node is an interface that implements just an ID field, which is meant to be an globally unique identifier for an object. IDs are designed to be opaque (typical convention is to base64('type:id')), applications should not attempt to rely on this implementation detail.
Node is exposed as part of the root Query, where applications can query against entities with known ID in a convenient way, e.g. refetching, fetching fields that have not been fetched.
{
node(id: ID!) {
... on User {
id
userId
name
}
... on Company {
id
companyId
owner: {
userId
name
}
}
...
}
}
This provides the convenience of not having to define query point for every model you expose (e.g. message(messageId) or user(userId)). We make our schema models inherit the Node interface to take advantage of this feature.
# Based on graphene-sqlalchemy, but should work the same for graphene-djangoclassQuery(graphene.ObjectType):
# Expose `node` as part of root query# Framework will extract `ID` and instantiate the object# base on the type and primary key informationnode=relay.Node.Field()
classUser(SQLAlchemyObjectType):
classMeta:
model=UserModel# Implements the `Node` interface.# Framework is smart enough to generate the `ID` value# base on the database object's primary key.interfaces= (relay.Node, )
One common gotcha is people often confuse ID with the object's identifier (e.g. primary key of the database object). They are not the same thing! Node.ID is a Relay/GraphQL implementation detail, and should not be meaningful in your application domain. My recommendation is to expose both ID and your object id in your schema. This gets tricky when your ORM primary key is named id, in which case you'll probably need to write a custom resolver.
This way your application can use the object id in a meaningful way, e.g in router's URL path, locating external resources, printing our reference numbers etc.
Connection
Like Node, Connection is also part of the Relay specs that made its way to mainstream adoption.
At first glance, the concept of edges seems superfluous but it does solve some tricky use case. Consider the need to expose a many-to-many relationship like 'friends', typically implemented in a database with a join table.
Oh my god, this is awesome!! In my own code I am actually using a CustomNode implementation that hides away the Relay-style ID and allows me to use Django's PKs, but I didn't want to show that in the talk because it would only make things even more complicated.
I have to read this a few more times and finally understand Nodes/Edges/IDs better and will try to change the code accordingly. I hope local_fields is also possible on the DjangoObjectType, exposing the PK that way would be awesome.
I hope local_fields is also possible on the DjangoObjectType, exposing the PK that way would be awesome.
AFAIK, graphene-django supports local_fields in the Meta as well (should work the same). Also checkout only_fields and exclude_fields for hiding ORM fields in schema.
Thank you @mbrochh for the introduction to the GraphQL stack at the Djangonauts meetup. Kudos to the well prepared presentation and sample codes.
I have a few thoughts and suggestions which I didn't raise during the meetup due to time constrain, hence I'm sharing it here for your consideration. (I'm relatively new to GraphQL so please take my words with a pinch of salt.)
Node
It may be worth mentioning that
Node
is part of the Facebook Relay specs (not GraphQL specs). However, most framework (Graphene included) implement this spec due to the close association between Relay and GraphQL.Essentially
Node
is an interface that implements just anID
field, which is meant to be an globally unique identifier for an object.ID
s are designed to be opaque (typical convention is tobase64('type:id')
), applications should not attempt to rely on this implementation detail.Node
is exposed as part of the root Query, where applications can query against entities with knownID
in a convenient way, e.g. refetching, fetching fields that have not been fetched.This provides the convenience of not having to define query point for every model you expose (e.g.
message(messageId)
oruser(userId)
). We make our schema models inherit the Node interface to take advantage of this feature.One common gotcha is people often confuse
ID
with the object's identifier (e.g. primary key of the database object). They are not the same thing!Node.ID
is a Relay/GraphQL implementation detail, and should not be meaningful in your application domain. My recommendation is to expose bothID
and your object id in your schema. This gets tricky when your ORM primary key is namedid
, in which case you'll probably need to write a custom resolver.This way your application can use the object id in a meaningful way, e.g in router's URL path, locating external resources, printing our reference numbers etc.
Connection
Like
Node
,Connection
is also part of the Relay specs that made its way to mainstream adoption.At first glance, the concept of
edges
seems superfluous but it does solve some tricky use case. Consider the need to expose a many-to-many relationship like 'friends', typically implemented in a database with a join table.It is now easy to display "Friends since [date here]" by exposing
friends.created_at
in the edge object.BTW,
cursor
is part of theConnection
specs which is exposed as a field onedge
.I hope you can find these information useful.
The text was updated successfully, but these errors were encountered: