Choosing Between GraphQL vs REST [Syntax Comparison]

April 19, 2022 • 927 Views • 17 min read

author photo

Tetiana Stoyko

CTO & Co-Founder

REST has long been a popular architectural paradigm for creating APIs, but GraphQL's rise in popularity in recent years has put REST's reign in jeopardy.

When it comes to establishing or leveraging API architecture design, the debate between GraphQL and REST is raging, and most firms are split between the two. While REST is generally recognized as the industry standard for creating APIs, GraphQL has been heralded as a new technology capable of overcoming REST's limitations. REST and GraphQL are two data retrieval technologies. The main distinction between GraphQL and RestAPIs is that GraphQL is a query language standard, whereas REST is an architectural idea for network-based computing.

We'll walk you through the working process with both options, and you’ll be able to compare which one is more fit for you: GraphQL vs REST. But first, let’s define the terms.

GraphQL Explanation

GraphQL is a runtime for satisfying queries with existing data, as well as an open-source data query and manipulation language for APIs. GraphQL, which is largely maintained and developed by the GraphQL Foundation, has seen tremendous acceptance across a wide range of verticals and use cases, including companies such as Twitter, Expedia, Shopify, and GraphCMS, to mention a few.

By allowing the user to receive just the data they expressly requested, this API architecture design eliminates any performance difficulties caused by extra fetching. Furthermore, many entities can be merged into a single query. GraphQL offers the advantage of tolerating client-side changes without affecting the server, allowing for quick front-end product updates. Developers that utilize GraphQL on the backend obtain a lot of information about any data request and how the available data is being used.

You may also be interested in the

RestAPI Definition

RestAPI today is a much easier technique to enable stateless and type-free machine-to-machine communication using only the ubiquitous HTTP protocol and no other layers. This made it possible for systems to be loosely connected and more tolerant of contract changes between systems, such as between businesses.

For firms delivering API architecture design and developing developer platforms, RestAPI has become the de facto norm. The benefit of REST is that it eliminates the need for any specific setup or libraries when interacting with someone else's API. Common tools such as cURL and web browsers can be used to send requests.

REST's key advantage is that it is scalable and decouples client and server, enabling developers to work independently on products and applications. It is adaptable to a wide number of forms and can suit a wide range of requirements.

Getting started

Now, we can compare both API architecture designs in practice. But, before we start with GraphQL vs REST installation descriptions, you need to install a typical Django project, connect it to PostgreSQL and make migrations. For the following work you also need to provide simple Django models:

Store in

models.py

from django.db import models


class Store(models.Model):
   name = models.CharField(max_length=256, verbose_name='Store name')
   address = models.CharField(max_length=256)
   email = models.EmailField()
   opening_hours = models.TimeField(verbose_name='Opening hours')
   closing_hours = models.TimeField(verbose_name='Closing hours')
   

And Product in another

models.py

file:

from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator


class Product(models.Model):
   title = models.CharField(max_length=256, verbose_name='Product title')
   description = models.TextField(max_length=5000)
   price = models.FloatField(
       validators=[MinValueValidator(0.0), MaxValueValidator(10000.0)],
   )
   amount = models.SmallIntegerField()
   store = models.ForeignKey('stores.Store', on_delete=models.CASCADE)

GraphQL in Django

Installation process:

pip install graphene-django

In

settings.py

file:

INSTALLED_APPS = [
    ...
    "django.contrib.staticfiles", # Required for GraphiQL
    "graphene_django"
]

GRAPHENE = {
    "SCHEMA": "app.schema.schema"
}

We need to add a graphql URL to the

urls.py

of your Django project:

from graphene_django.views import GraphQLView

from django.contrib import admin
from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from app.schema import schema

urlpatterns = [
   path('admin/', admin.site.urls),
   path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
]

For querying process (like use GET) you need to provide object types and resolvers:

import graphene
from graphene_django import DjangoObjectType
from app.stores.models import Store
from app.products.models import Product

class StoreType(DjangoObjectType):
   class Meta:
       model = Store
       fields = (
           'id', 'name', 'address', 'email', 'opening_hours', 'closing_hours',
       )


class ProductType(DjangoObjectType):
   class Meta:
       model = Product
       fields = (
           'id', 'title', 'description', 'price', 'amount', 'store',
       )


class Query(graphene.ObjectType):
   stores = graphene.List(StoreType)
   products = graphene.List(ProductType)

   def resolve_stores(root, info, **kwargs):
       # Querying a list
       return Store.objects.all()

   def resolve_products(root, info, **kwargs):
       # Querying a list
       return Product.objects.all()

schema = graphene.Schema(query=Query)

GraphQL Testing

For testing you can just type

http://127.0.0.1:8000/graphql

in your browser:

graph1.png

If you want something to change (create or update) you need to provide inputs and create/update class with arguments and mutation methods:

class StoreInput(graphene.InputObjectType):
   name = graphene.String()
   address = graphene.String()
   email = graphene.String()
   opening_hours = graphene.Time()
   closing_hours = graphene.Time()


class CreateStore(graphene.Mutation):
   class Arguments:
       input = StoreInput(required=True)

   store = graphene.Field(StoreType)

   @classmethod
   def mutate(cls, root, info, input):
       store = Store()
       store.name = input.name
       store.address = input.address
       store.email = input.email
       store.opening_hours = input.opening_hours
       store.closing_hours = input.closing_hours
       store.save()
       return CreateStore(store=store)

class UpdateStore(graphene.Mutation):
   class Arguments:
       input = StoreInput(required=True)
       id = graphene.ID()

   store = graphene.Field(StoreType)

   @classmethod
   def mutate(cls, root, info, input, id):
       store = Store.objects.get(pk=id)
       store.name = input.name
       store.address = input.address
       store.email = input.email
       store.opening_hours = input.opening_hours
       store.closing_hours = input.closing_hours
       store.save()
       return UpdateStore(store=store)


class ProductInput(graphene.InputObjectType):
   title = graphene.String()
   description = graphene.String()
   price = graphene.Float()
   amount = graphene.Int()
   store = graphene.ID()


class CreateProduct(graphene.Mutation):
   class Arguments:
       input = ProductInput(required=True)

   product = graphene.Field(ProductType)

   @classmethod
   def mutate(cls, root, info, input):
       product = Product()
       product.title = input.title
       product.description = input.description
       product.price = input.price
       product.amount = input.amount
       product.store = input.store
       product.save()
       return CreateProduct(product=product)

class UpdateProduct(graphene.Mutation):
   class Arguments:
       input = ProductInput(required=True)
       id = graphene.ID()

   product = graphene.Field(ProductType)

   @classmethod
   def mutate(cls, root, info, input, id):
       product = Product.objects.get(pk=id)
       product.title = input.title
       product.description = input.description
       product.price = input.price
       product.amount = input.amount
       product.store = input.store
       product.save()
       return UpdateProduct(product=product)

class Mutation(graphene.ObjectType):
   create_store = CreateStore.Field()
   update_store = UpdateStore.Field()
   update_product = CreateProduct.Field()
   create_product = UpdateProduct.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)

Also, you can test creation in the browser:

graph2.png

RestAPI in Django

Installation process:

pip install djangorestframework

In

settings.py

file:

INSTALLED_APPS = [
   ...
   'rest_framework',
]

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

You should make serializers in

products/serializers.py

:

from rest_framework import serializers

from .models import Product


class ProductSerializer(serializers.ModelSerializer):
   class Meta:
       model = Product
       fields = '__all__'

And also, in

stores/serializers.py

:

from rest_framework import serializers

from .models import Store


class StoreSerializer(serializers.ModelSerializer):
   class Meta:
       model = Store
       fields = '__all__'

After this you need to make your views:

from rest_framework import generics
from rest_framework.permissions import AllowAny

from .serializers import ProductSerializer
from .models import Product


class RetriveUpdateDestroyProductView(generics.RetrieveUpdateDestroyAPIView):
   queryset = Product.objects.all()
   serializer_class = ProductSerializer
   permission_classes = [AllowAny]


class ListCreateProductView(generics.ListCreateAPIView):
   queryset = Product.objects.all()
   serializer_class = ProductSerializer
   permission_classes = [AllowAny]

from rest_framework import generics
from rest_framework.permissions import AllowAny

from .serializers import StoreSerializer
from .models import Store


class RetriveUpdateDestroyStoreView(generics.RetrieveUpdateDestroyAPIView):
   queryset = Store.objects.all()
   serializer_class = StoreSerializer
   permission_classes = [AllowAny]


class ListCreateStoreView(generics.ListCreateAPIView):
   queryset = Store.objects.all()
   serializer_class = StoreSerializer
   permission_classes = [AllowAny]

And connect it in

urls.py

file:

In

app/stores/urls.py

from django.urls import path
from .views import ListCreateStoreView, RetriveUpdateDestroyStoreView


urlpatterns = [
   path('<int:pk>/', RetriveUpdateDestroyStoreView.as_view(), name='store-get-update-delete'),
   path('', ListCreateStoreView.as_view(), name='store-post-list'),
]

In

app/products/urls.py

from django.urls import path
from .views import ListCreateProductView, RetriveUpdateDestroyProductView


urlpatterns = [
   path('<int:pk>/', RetriveUpdateDestroyProductView.as_view(), name='product-get-update-delete'),
   path('', ListCreateProductView.as_view(), name='product-post-list'),
]

And in

app/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
   path('admin/', admin.site.urls),
   path('store/', include('app.stores.urls')),
   path('product/', include('app.products.urls')),
]

RestAPI Testing

After this you can test it in Postman.

For getting products:

rest1.png

And creating a new store:

rest2.png

GraphQL vs REST

If we compare the examples of the two API integration designs, we can see that the implementation of GraphQL requires more description of the logic of creating new objects, and in the RestAPI there are many ready-made solutions out of the box. That is, GraphQL requires a more complex implementation. Instead, GraphQL adds usability. For example, to make a query and get additional fields you need to register them when querying. At the same time for RestAPI, if you need new fields, then the backend needs to implement new serializers. Also, using GraphQL requires fewer queries to get the information you need. This is important when the Internet may not be good enough (for example, on mobile devices that use a mobile network).

GraphQL is more focused on the client-side than well-created documentation, which is created independently. However, among the negatives can be called incompatibility with HTTP. You cannot use statuses (only 200 and 500 are used) and methods (POST only). That takes away flexibility in the processing of errors on a client's part. It is also quite problematic to implement caching in GraphQL due to the use of a single endpoint in different queries.

As for security, GraphQL needs to be worked on further, because with the help of queries to different graphs, you can make a query to another user through the rock store to which they belong. In REST there is no such problem as the client receives only what is registered in the endpoint.

Summary: How to choose?

GraphQL is fairly new compared to RestAPI, and it's easy to use. Its flexibility and high query speed make it a great alternative to RestAPI. GraphQL will be brilliant when you need a quick interface development, and you expect the program to respond quickly and in a short amount of time. REST, on the other hand, is a more suitable solution for more complex programs with more caching and bug reports. It all comes down to your needs.

Some APIs, such as analytics APIs, may not be suitable for GraphQL since they have a small number of entities and connections between them. GraphQL may be more useful in applications with a large number of domain objects, such as e-commerce, where you have goods, users, orders, payments, and so on. However, obviously, to make a decision that won’t affect your app’s performance lately in a bad way, it’s better to confide in software development experts. At Incora, we will analyze the possible functionality and details of an app first, and just then - advise. Contact us, and we will help you decide!

Share this post

Tags

Tech
Comparison
Guide

What’s your impression after reading this?

Love it!

Valuable

Exciting

Unsatisfied

Got no clue where to start? Why don’t we discuss your idea?

Let’s talk!

Contact us

chat photo
privacy policy

© 2015-2024 Incora LLC

offices

Ukrainian office

116, Bohdana Khmel'nyts'koho, Lviv, Lviv Oblast, 79019

USA office

16192 Coastal Hwy, Lewes, DE 19958 USA

follow us

This site uses cookies to improve your user experience.Read our Privacy Policy

Accept