April 19, 2022 • 927 Views • 17 min read
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 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 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.
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)
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)
For testing you can just type
http://127.0.0.1:8000/graphql
in your browser: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:
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')),
]
After this you can test it in Postman.
For getting products:
And creating a new store:
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.
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
Love it!
Valuable
Exciting
Unsatisfied
YOU MAY ALSO LIKE
Let’s talk!
This site uses cookies to improve your user experience.Read our Privacy Policy
Accept