Getting Started
Quickstart Guide
We are going to create a simple blog application with a gRPC service.
The blog application will have the following models: User
and Post
.
Prerequisites
You will need to install the following packages:
Python (>= 3.8)
Installation
Install the package via pip:
pip install django-socio-grpc
Creating a New Project
Now you can create the project by running the following command :
django-admin startproject dsg_tutorial
Add now the following lines to the INSTALLED_APPS
section of your dsg_tutorial/settings.py
file:
INSTALLED_APPS = [
...
'django_socio_grpc',
]
See Django tutorial for more information
Adding a New App
Then create a new app. First, cd into the project directory:
cd dsg_tutorial
Create the new app:
python manage.py startapp quickstart
This will create a new directory called quickstart
inside your project directory including python files.
Add the new app to the INSTALLED_APPS
section of your dsg_tutorial/settings.py
file:
INSTALLED_APPS = [
...
'quickstart',
]
Finally migrate the database:
python manage.py migrate
See Django tutorial for more information
Defining models
Create your models as described in the Django documentation .
Each model is assigned to a table in the database.
It inherits from django.db.models.Model
Django class.
Each attribute represents a field in the table.
For directly working with the database, use the usual Django API (see Query creation).
#quickstart/models.py
from django.db import models
class User(models.Model):
full_name = models.CharField(max_length=70)
class Post(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
Defining serializers
Serializers convert the data from the Django database into protobuf format, that can be sent over the network via gRPC, and also back from protobuf into the Django database.
In this simple example, our serializers inherit from ModelProtoSerializer, which is simply an inheritance of DRF’s ModelSerializer. For more extensive use, you can use all the DRF serializer methods: Django REST framework serializers.
See ProtoSerialzer doc page for more information.
#quickstart/serializers.py from django_socio_grpc import proto_serializers from rest_framework import serializers from quickstart.models import User, Post class UserProtoSerializer(proto_serializers.ModelProtoSerializer): # This line is written here as an example, # but can be removed as the serializer integrates all the fields in the model full_name = serializers.CharField(allow_blank=True) class Meta: model = User fields = "__all__" class PostProtoSerializer(proto_serializers.ModelProtoSerializer): pub_date = serializers.DateTimeField(read_only=True) class Meta: model = Post fields = "__all__"
Defining gRPC services
Services define the gRPC actions that can be performed, e.g., on your models. Its what is used to generate the protobuf files and gRPC stubs. So all the gRPC actions that you want in your proto file should be declared or inhetited in your service.
The gRPC service is the equivalent of the DRF APIView and behaves in a similar way (it only contains an additional internal layer). See additional note after example for comparaison.
In the the following example we will create 2 services.
UserService
, will be a read-only service (AsyncReadOnlyModelService
), meaning that it will have 2 gRPC actions: List and Retrieve.PostService
, will be a read-write service (AsyncModelService
), meaning that it will have 6 gRPC actions: List, Retrieve, Create, Update, PartialUpdate, Destroy.
See Mixin section and Proto generation documentation to help you understand how actions are declared.
#quickstart/services.py
from django_socio_grpc import generics
from quickstart.models import User, Post
from quickstart.serializer import UserProtoSerializer, PostProtoSerializer
# This service will have only the List and Retrieve actions
class UserService(generics.AsyncReadOnlyModelService):
queryset = User.objects.all()
serializer_class = UserProtoSerializer
# This service will have all the CRUD actions
class PostService(generics.AsyncModelService):
queryset = Post.objects.all()
serializer_class = PostProtoSerializer
Warning
DSG supports both sync and async, but we recommend using async services, since sync services will be deprecated in the future versions of DSG.
Note
DSG Generic services and mixins are based on DRF Generic views and mixins, so you can create your services in a similar way as you would do with DRF in a class-based services, e.g.:
In DSG :
from django.contrib.auth.models import User
from quickstart.serializers import UserProtoSerializer
from django_socio_grpc import generics
# This is and example of a custom service
class MyListService(generics.ListCreateService):
queryset = User.objects.all()
serializer_class = UserProtoSerializer
In DRF :
from django.contrib.auth.models import User
from quickstart.serializers import UserProtoSerializer
from rest_framework import generics
class MyListService(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserProtoSerializer
Register services
You need to register your services in a handler function.
This handler will be the entrypoint for your whole app.
In this quickstart, we will register our services in the quickstart/handlers.py
file.
# quickstart/handlers.py
from django_socio_grpc.services.app_handler_registry import AppHandlerRegistry
from quickstart.services import UserService, PostService
def grpc_handlers(server):
app_registry = AppHandlerRegistry("quickstart", server)
app_registry.register(UserService)
app_registry.register(PostService)
Set its path as the ROOT_HANDLERS_HOOK
of the GRPC_FRAMEWORK
settings:
# quickstart/settings.py
...
GRPC_FRAMEWORK = {
"ROOT_HANDLERS_HOOK" : 'quickstart.handlers.grpc_handlers',
...
}
Note
To better understand the register process and have recommandation about the handlers.py
file for more complex project please read the Service Registry documentation
Generate the app’s Protobuf files and gRPC stubs
To generate (and update) the .proto files and gRPC stubs from the services defined in service.py, you need to run the following command:
python manage.py generateproto
See Proto generation for more information.
This will generate a folder called grpc
at the root of your Django app.
It contains the three files describing your new gRPC service:
quickstart_pb2_grpc.py
quickstart_pb2.py
quickstart.proto
DSG generate all the file needed by gRPC. Meaning that you don’t need to deal with protofile manually.
Assign newly generated classes
In the newly generated quickstart/grpc/quickstart.proto
file,
you can find the structure of Service, responses message and requests message.
For each serializer of your app attached to a service, you will find the associated protobuf message. If the serializer is used as a list you will also find the associated list message.
To let the DSG magic opere you need to manually (for now) reassign this generated message to the Serializer. This message exit in python class in the generated pb2
file.
You only need to import the messages in the serializers.py
file and assign them to the serializers, like in the following example:
#quickstart/serializers.py
...
from quickstart.grpc.quickstart_pb2 import (
UserResponse,
UserListResponse,
PostResponse,
PostListResponse,
)
class UserProtoSerializer(proto_serializers.ModelProtoSerializer):
...
class Meta:
...
proto_class = UserResponse
proto_class_list = UserListResponse
class PostProtoSerializer(proto_serializers.ModelProtoSerializer):
...
class Meta:
...
proto_class = PostResponse
proto_class_list = PostListResponse
Running the Server
You can now run the gRPC server with the following command:
python manage.py grpcrunaioserver --dev
The server is now running on port 50051 by default. See How To Web to see how to call this server with web client or Python example for python client example.
To read more about the grpcrunaioserver please read the commands documentation
To continue reading consider read: