GraphQL Simplistic CRUD
This is my first time playing with GraphQL, but it is not my first time developing Django CRUD API endpoint. I have done with Django REST Framework(DRF) for several projects. My seniors guided me very well
The goals of this article are CRUD on one single model instance. I know they are 3 approaches that GraphQL can do with mutations(ModelForm, ModelSerializer, and Relay)
And to delete the instance you have to customize you own way
Let’s get started from naive approach with single model single endpoint not use any filter yet to keep my article short
First one model
and serializer
I would like to follow DRF approach because it is not only do a validation like `ModelForm`, but also support nested payload
from graphene_django import DjangoObjectType
from rest_framework import serializersclass Question(models.Model):
question_text = models.CharField(max_length=50)class QuestionSerializer(serializers.ModelSerializer):
class Meta:
model = Question
fields = (
'id',
'question_text',
)class QuestionType(DjangoObjectType): class Meta:
model = Question
fields = (
'id',
'question_text',
'category',
)
Mutation POST/UDATE/DELETE
I have to customize my own DELETE
`ok` field might now make any sense for you, but you will see it in action soon
class DeleteQuestion(graphene.Mutation):
ok = graphene.Boolean()
class Arguments:
id = graphene.ID()
@classmethod
def mutate(cls, root, info, **kwargs):
obj = Question.objects.get(id=kwargs.get('id'))
obj.delete()
return cls(ok=True)class QuestionSerializerMutation(SerializerMutation):
delete_question = DeleteQuestion.Field()
class Meta:
serializer_class = QuestionSerializer
model_operation = ['crated', 'update']
lookup_field = 'id'
And Mutation
class with remarkable name
class Mutation(graphene.ObjectType):
xxx = QuestionSerializerMutation.Field()class QPQuery(graphene.ObjectType):
questions = graphene.List(QuestionType)
question = graphene.Field(QuestionType,
question_id=graphene.String(),
bar=graphene.Int()) def resolve_questions(self, info, **kwargs):
return Question.objects.all()
def resolve_question(self, info, question_id, bar):
print(bar)
return Question.objects.get(pk=question_id)
And schema
schema = graphene.Schema(query=QPQuery, mutation=Mutation)
Analogy with traditional HTTP method
GET List
query{
questions{
id
questionText
}
}
Response. Almost good I will cover the filter, pagination and authentication later day
{
"data": {
"questions": [
{
"id": "5",
"questionText": "qKRDzeRqFapnNGuvhGVdmdDZJCUBPUpwaTNgNJDKzpTAnuklmk"
},
{
"id": "6",
"questionText": "WLYiBpnZPpJdGstouKzGgSnLfMsGiXaRWqKJMQCVKMIucAZQJc"
},
{
"id": "8",
"questionText": "Batman"
}
]
}
}
GET Detail
{
"data": {
"question": {
"id": "8",
"questionText": "Batman"
}
}
}
POST Create
mutation{
xxx(input: {questionText: "How to get rich?"}){
id
questionText
errors{
field
messages
}
}
}
In order to get the error messages you have to add errors
PATCH/PUT Update
mutation{
xxx(input: {id: 8, questionText: "How to heal my burn wound?"}){
id
questionText
}
}
DELETE
It seems redundant here because I have to fill in input
2 times. I will optimize my endpoint in later time
mutation{
xxx(input: {id: 10, questionText: ""}){
deleteQuestion(id:10){
ok
}
}
}
GraphQL is good, but document is not mature yet. I spent my time 3 hours to figure out the endpoint which is OK for me. Hope tooling engineer will supply more recipe on this great tool.