### Add quickstart app to Django INSTALLED_APPS Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Registers the newly created `quickstart` app by adding it to the `INSTALLED_APPS` list in `dsg_tutorial/settings.py`. This makes the `quickstart` app's components, such as models, available to the Django project. ```python INSTALLED_APPS = [ ... 'quickstart', ] ``` -------------------------------- ### Change directory and create a new Django app Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Navigates into the newly created Django project directory `dsg_tutorial` and then generates a new Django application named `quickstart`. This app will house the models, serializers, and gRPC services for the blog application. ```bash cd dsg_tutorial ``` ```bash python manage.py startapp quickstart ``` -------------------------------- ### Install django-socio-grpc via pip Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Installs the `django-socio-grpc` package using pip, which is required for building gRPC services with Django. This command ensures all necessary dependencies are downloaded and installed. ```bash pip install django-socio-grpc ``` -------------------------------- ### Create a new Django project Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Initializes a new Django project named `dsg_tutorial` using the `django-admin` command-line utility. This sets up the basic directory structure and essential project files. ```bash django-admin startproject dsg_tutorial ``` -------------------------------- ### Run Django gRPC Server Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This command sequence initializes the database schema and starts the Django gRPC server. `makemigrations` and `migrate` prepare the database, while `grpcrunaioserver --dev` launches the server in development mode, typically on port 50051. ```python python manage.py makemigrations python manage.py migrate python manage.py grpcrunaioserver --dev ``` -------------------------------- ### Add django-socio-grpc to Django INSTALLED_APPS Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Configures the Django project by adding `django_socio_grpc` to the `INSTALLED_APPS` list in `dsg_tutorial/settings.py`. This step enables the `django-socio-grpc` framework within your Django application. ```python INSTALLED_APPS = [ ... 'django_socio_grpc', ] ``` -------------------------------- ### Apply Django database migrations Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Executes database migrations for the Django project using `python manage.py migrate`. This command creates or updates database tables based on the defined models in your Django applications. ```bash python manage.py migrate ``` -------------------------------- ### Verify Pytest Installation Version Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/testing.rst This command is used to check if `pytest` is correctly installed and to display its current version. It's a quick way to confirm your testing environment setup. ```bash pytest --version ``` -------------------------------- ### Define Django REST Framework ProtoSerializers Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Implements `UserProtoSerializer` and `PostProtoSerializer` in `quickstart/serializers.py`. These serializers, inheriting from `ModelProtoSerializer`, handle the conversion of Django model instances to and from protobuf format, facilitating data exchange over gRPC. ```python #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__" ``` -------------------------------- ### Compare Django Socio gRPC Service with DRF Generic View Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This example illustrates the structural similarity between defining a custom service in Django Socio gRPC (DSG) and a generic view in Django REST Framework (DRF). Both patterns use `queryset` and `serializer_class` for common operations like listing and creating resources. ```python 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 ``` ```python 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 ``` -------------------------------- ### Define Django models for User and Post Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Defines `User` and `Post` models in `quickstart/models.py` for a simple blog application. These models specify the database schema, including fields like `full_name`, `pub_date`, `headline`, `content`, and a `ForeignKey` relationship between `Post` and `User`. ```python #quickstart/models.py from django.db import models class User(models.Model): full_name = models.CharField(max_length=70) class Post(models.Model): # If you are using Django >= 5.0, consider using `db_default` instead of `auto_now_add`: https://docs.djangoproject.com/en/5.1/ref/models/fields/#django.db.models.Field.db_default pub_date = models.DateField(auto_now_add=True) headline = models.CharField(max_length=200) content = models.TextField() user = models.ForeignKey(User, on_delete=models.CASCADE) ``` -------------------------------- ### django-socio-grpc AsyncReadOnlyModelService Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst Documents the `AsyncReadOnlyModelService` from `django_socio_grpc.generics`, which is designed to provide read-only gRPC operations for Django models. It exposes two primary gRPC actions: `List` for fetching collections of resources and `Retrieve` for accessing individual resources. ```APIDOC django_socio_grpc.generics.AsyncReadOnlyModelService: - Purpose: Provides read-only gRPC actions for Django models. - Inherits from: Similar to DRF's APIView but with an additional internal layer. - Supported gRPC Actions: - List: - Description: Retrieves a collection of model instances. - Equivalent to: DRF's ListAPIView. - Retrieve: - Description: Retrieves a single model instance by its identifier. - Equivalent to: DRF's RetrieveAPIView. ``` -------------------------------- ### Generate Protobuf Files and gRPC Stubs for Django Socio gRPC Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This command-line snippet demonstrates how to use the Django management command `generateproto`. Running this command automatically creates or updates the necessary Protobuf (.proto) files and gRPC stub files (`_pb2.py`, `_pb2_grpc.py`) based on the defined Django Socio gRPC services. ```python python manage.py generateproto ``` -------------------------------- ### Register Django Socio gRPC Services in Handler Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This snippet demonstrates how to register defined gRPC services (`UserService`, `PostService`) using `AppHandlerRegistry` within a `grpc_handlers` function. This function serves as the central entry point for the gRPC application, mapping services to the gRPC server. ```python # 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 Up a Django Socio gRPC Test Case with Mock Server Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/testing.rst This Python code illustrates the setup of a `TestCase` for Django Socio gRPC services. It shows how to instantiate `FakeFullAIOGRPC` within the `setup` method, providing the gRPC-generated servicer adder function and the service instance. This configuration creates a mock gRPC server, enabling direct testing of gRPC service methods without actual network communication. ```python # quickstart/tests.py from django.test import TestCase from .post.services.post_service import PostService from .post.grpc import post_pb2 from .post.grpc.post_pb2_grpc import ( PostControllerStub, add_PostControllerServicer_to_server, ) from .grpc_test_utils.fake_grpc import FakeFullAIOGRPC class TestPost(TestCase): def setup(self): self.fake_grpc = FakeFullAIOGRPC( add_PostControllerServicer_to_server, PostService.as_servicer(), ) ``` -------------------------------- ### Configure Django Socio gRPC Root Handlers Hook Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This configuration snippet shows how to set the `ROOT_HANDLERS_HOOK` within the `GRPC_FRAMEWORK` settings in Django. This setting points to the `grpc_handlers` function, which is responsible for registering all gRPC services with the server. ```python # dsg_tutorial/settings.py ... GRPC_FRAMEWORK = { "ROOT_HANDLERS_HOOK" : 'quickstart.handlers.grpc_handlers', ... } ``` -------------------------------- ### Create Secure gRPC Client Channel in Python Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/work-with-secure-port.rst This Python example illustrates how to establish a secure gRPC client channel using `grpc.ssl_channel_credentials` and `grpc.aio.secure_channel`. It reads a certificate file to create channel credentials, enabling encrypted communication with a gRPC server and supporting client-side authentication if required by the server. The example includes an asynchronous main function to demonstrate channel usage. ```python import asyncio import grpc def create_client_channel(addr: str) -> grpc.aio.Channel: with open("/path/to/certificates.pem", "rb") as certificate_file: # Channel credential will be valid for the entire channel. See https://grpc.github.io/grpc/python/grpc.html#grpc.ssl_channel_credentials channel_credential = grpc.ssl_channel_credentials( certificate_file.read() ) channel = grpc.aio.secure_channel(addr, channel_credential) return channel async def main() -> None: channel = create_client_channel("localhost:50051") # Mock method that make an RPC. If don't know how to make a rpc call see Examples section await send_rpc(channel) await channel.close() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Define Django Socio gRPC Services Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This snippet demonstrates how to define gRPC services in Django Socio gRPC. It shows `AsyncReadOnlyModelService` for read-only operations (List, Retrieve) and `AsyncModelService` for full CRUD operations (List, Retrieve, Create, Update, PartialUpdate, Destroy), utilizing Django querysets and Proto serializers. ```python #quickstart/services.py from django_socio_grpc import generics from quickstart.models import User, Post from quickstart.serializers 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 ``` -------------------------------- ### Assign Generated Protobuf Messages to Django Socio gRPC Serializers Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst This snippet illustrates how to import and assign the automatically generated Protobuf message classes (e.g., `UserResponse`, `PostListResponse`) from the `_pb2.py` file to their corresponding Django Socio gRPC serializers. This manual reassignment is crucial for DSG's internal mapping and proper functioning. ```python #quickstart/serializers.py ... from quickstart.grpc.quickstart_pb2 import ( UserResponse, UserListResponse, PostResponse, PostListResponse, ) ``` -------------------------------- ### Define ProtoSerializers for Django Models Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/getting-started.rst These Python classes demonstrate how to extend `ModelProtoSerializer` to map Django models to gRPC message structures. The `Meta` class specifies the `proto_class` and `proto_class_list` for single and list responses, respectively, enabling automatic gRPC message generation. ```python 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 ``` -------------------------------- ### Set up local development environment with Docker Compose Source: https://github.com/socotecio/django-socio-grpc/blob/master/README.md These commands initialize and migrate the database for local development using Docker Compose. `docker compose up` starts the services, and the subsequent command runs migrations within the Django container. ```Bash docker compose up docker compose exec django-socio-grpc poetry run python test_utils/migrate.py ``` -------------------------------- ### JavaScript gRPC Web Client Example with connect-web Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/authentication-permissions.rst Illustrates how to set up a gRPC web client in JavaScript using `@connectrpc/connect` and `@connectrpc/connect-web`. It covers creating a transport, a promise client, and making an authenticated gRPC call with custom headers, then logging the response. ```Javascript import { MyServiceController } from '../gen/example_bib_app_connect' import { createPromiseClient } from "@connectrpc/connect"; import { createGrpcWebTransport } from "@connectrpc/connect-web"; const transport = createGrpcWebTransport({ baseUrl: "http://localhost:9001", }); const authorClient = createPromiseClient(MyServiceController, transport); let headers = {"headers": JSON.stringify({"Authorization": "faketoken"})} // See https://connectrpc.com/docs/web/headers-and-trailers const res = await authorClient.list( {}, {headers: headers} ) console.log(res) let items = res.results ``` -------------------------------- ### Example Django Models, Serializers, and gRPC Service for Proto Generation Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/proto-generation.rst This comprehensive example demonstrates the necessary Django components (models, serializers) and Django Socio gRPC service definitions required for automatic Protobuf file generation. It includes a custom gRPC action with defined request and response types. ```python # quickstart/models.py from django.db import models class User(models.Model): full_name = models.CharField(max_length=70) def __str__(self): return self.full_name # quickstart/serializers.py from django_socio_grpc import proto_serializers from rest_framework import serializers from quickstart.models import User 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__" # Service (quickstart/services.py) from django_socio_grpc import generics from django_socio_grpc.decorators import grpc_action from ..models import User from ..serializers import UserProtoSerializer # inherits from AsyncModelService, therefore will register all default CRUD actions. class UserService(generics.AsyncModelService): queryset = User.objects.all() serializer_class = UserProtoSerializer @grpc_action async def SomeCustomMethod( request=[{"name": "foo", "type": "string"}], response=[{"name": "bar", "type": "string"}], response_stream=True ): # logic here pass # quickstart/handlers.py from django_socio_grpc.services.app_handler_registry import AppHandlerRegistry from quickstart.services import UserService def grpc_handlers(server): app_registry = AppHandlerRegistry("quickstart", server) app_registry.register(UserService) ``` -------------------------------- ### Install Django Socio gRPC using pip Source: https://github.com/socotecio/django-socio-grpc/blob/master/README.md This command installs the `django-socio-grpc` package into your Python environment using pip. It's the first step to integrate the toolkit into your Django project. ```Bash pip install django-socio-grpc ``` -------------------------------- ### Example Log Formatters for Django-Socio-gRPC Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/add-extra-context-to-logging.rst This Python dictionary provides examples of log formatters. The `django_socio_grpc_formatter` demonstrates how to incorporate the custom `grpc_service_name`, `grpc_action`, and `grpc_user_pk` fields, which are injected into log records by the custom log record factory, into the log output format. ```python "formatters": { "django_socio_grpc_formatter": { "format": "[django]-[%(levelname)s]-[%(asctime)s]-[%(name)s:%(lineno)s] [{grpc_service_name} {grpc_action} {grpc_user_pk}] %(message)s" }, "simple": { "format": "[django]-[%(levelname)s]-[%(asctime)s]-[%(name)s:%(lineno)s] %(message)s" } } ``` -------------------------------- ### Configure ROOT_HANDLERS_HOOK for gRPC Service Registration Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/settings.rst This setting points to the `grpc_handlers` function responsible for registering all gRPC Services for the project's applications. It runs just before the server starts, useful for initializations. The example shows how to set this path for a project named 'my_project'. ```python "ROOT_HANDLERS_HOOK": "my_project.handlers.grpc_handlers" ``` -------------------------------- ### Execute All Pytest Tests Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/testing.rst This command initiates the test discovery and execution process using `pytest`. It runs all tests found in the project, providing feedback on their pass/fail status. ```bash pytest ``` -------------------------------- ### Define Django Book Model Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/examples/async-simple-bib-example.rst Defines the Django `Book` model, which serves as the data structure for the bibliographic service. This model includes fields for title, author, ISBN, publisher, and publication date, providing a foundation for CRUD operations. ```python class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=100) isbn = models.CharField(max_length=20) publisher = models.CharField(max_length=100) publication_date = models.DateField() ``` -------------------------------- ### gRPC-Web Ecosystem Client Implementations Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/grpc-web.rst This section describes the various client options available for consuming the generated gRPC-Web files in a browser environment. It covers direct usage of gRPC-web generated classes, the Improbable client, and the BUF Connect client, highlighting their respective compatibilities and usage examples. ```APIDOC 1. gRPC-web generated class directly: - Usage: Directly utilize the classes generated by the gRPC-web compiler. - Example: https://github.com/grpc/grpc-web#option-using-promises-limited-features 2. Improbable: - Compatibility: Works seamlessly with files generated by gRPC-web. - Example: https://github.com/improbable-eng/grpc-web#example 3. BUF connect: - Compatibility: Designed to work with files generated by the BUF CLI. - Example: https://connectrpc.com/docs/web/using-clients/ ``` -------------------------------- ### Example of Custom Django Socio gRPC Locale Middleware Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/middlewares.rst This Python example demonstrates the structure and partial implementation of a custom `locale_middleware` for Django Socio gRPC. It illustrates how to use the `@sync_and_async_middleware` decorator to support both synchronous and asynchronous request handling, adapting to the `get_response` function's type. ```python import asyncio from typing import Callable from django.utils import translation from django.utils.decorators import sync_and_async_middleware from django_socio_grpc.services.servicer_proxy import GRPCRequestContainer from django_socio_grpc.utils.utils import safe_async_response # This decorator declares the middleware as supporting # both synchronous and asynchronous requests. @sync_and_async_middleware # get_response is the next middleware (or the actual GRPCAction if last) def locale_middleware(get_response: Callable): # As it is supporting both synchronous and asynchronous requests, # it returns a sync or async function depending on the type of get_response. if asyncio.iscoroutinefunction(get_response): async def middleware(request: GRPCRequestContainer): ``` -------------------------------- ### Transforming Django Cache Decorator for gRPC with Request Simulation Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/use-django-decorators-in-dsg.rst This Python example demonstrates a more advanced use case, adapting Django's `cache_page` decorator for gRPC methods. It utilizes `http_to_grpc` along with `method_decorator` (implicitly used or assumed to be available) to apply caching logic. The `request_setter` parameter is used to simulate a `GET` HTTP method for caching purposes, and `support_async` is set to `False` to handle potential async compatibility issues with certain cache backends. `functools.wraps` is included for proper decorator metadata preservation. ```python from django_socio_grpc.decorators import http_to_grpc from django.views.decorators.cache import cache_page @functools.wraps(cache_page) def cache_endpoint(*args, **kwargs): return http_to_grpc( method_decorator(cache_page(*args, **kwargs)), request_setter={"method": "GET"}, support_async=False ) ``` -------------------------------- ### Configure Django INSTALLED_APPS for Django Socio gRPC Source: https://github.com/socotecio/django-socio-grpc/blob/master/README.md After installation, add `django_socio_grpc` to your Django project's `INSTALLED_APPS` setting. This registers the application with Django, making its features available. ```Python INSTALLED_APPS = [ ... 'django_socio_grpc', ] ``` -------------------------------- ### Organizing Django gRPC Service Handlers Across Multiple Applications Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/inner-workings/services-registry.rst This example illustrates a best practice for structuring `grpc_handlers` across a multi-app Django project. Each app defines its own handler to register services, which are then imported and called from a central project-level handler. This approach enhances modularity and simplifies service management. ```python # my_first_app.handlers.py from django_socio_grpc.services.app_handler_registry import AppHandlerRegistry from my_first_app.service import MyFirstAppService def grpc_handlers(server): app_registry = AppHandlerRegistry("my_first_app", server) app_registry.register(MyFirstAppService) ``` ```python # my_second_app.handlers.py from django_socio_grpc.services.app_handler_registry import AppHandlerRegistry from my_second_app.service import MyFirstAppService def grpc_handlers(server): app_registry = AppHandlerRegistry("my_second_app", server) app_registry.register(MyFirstAppService) ``` ```python # my_project.handlers.py from django_socio_grpc.services.app_handler_registry import AppHandlerRegistry from my_first_app.handlers import grpc_handlers as my_first_app_grpc_handlers from my_second_app.handlers import grpc_handlers as my_second_app_grpc_handlers ``` -------------------------------- ### Define Service-Specific Authentication and Permission Classes Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/authentication-permissions.rst This example illustrates how to apply authentication and permission classes directly to a specific Django-Socio-gRPC service. By setting `authentication_classes` and `permission_classes` attributes on an `AsyncModelService` subclass, you can override global settings and enforce granular access control for individual services. ```python from oidc_auth.authentication import JSONWebTokenAuthentication from rest_framework.permissions import IsAuthenticated from django_socio_grpc.generics import AsyncModelService class ExampleService(AsyncModelService): authentication_classes = [JSONWebTokenAuthentication] permission_classes = [IsAuthenticated] ``` -------------------------------- ### Example log output for gRPC service exceptions Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/logging.rst This plain text snippet displays the expected console output when the `SomethingService` (defined previously) is executed with the specified Django logging configuration. It demonstrates how `GRPCException` (NotFound) results in a 'WARNING' log, while other exceptions (ValueError) result in an 'ERROR' log, as configured by `django_socio_grpc.request`. ```text WARNING NotFound : SomethingService/RaiseGRPCException ERROR ValueError : SomethingService/RaiseUncaughtException ``` -------------------------------- ### Client-Side Unidirectional gRPC File Upload Example in Python Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/upload-file.rst This Python example demonstrates a client-side implementation for performing a unidirectional gRPC file upload. It reads a local file in chunks, creates `FileChunk` messages, and streams them to the gRPC server's `UploadFile` method, printing the upload status received from the server. ```python import grpc from my_app.grpc.my_appp_pb2 as file_upload_pb2 from my_app.grpc.my_appp_pb2_grpc as file_upload_pb2 def upload_file(stub, file_path): with open(file_path, 'rb') as file: for chunk in read_in_chunks(file): # Create a FileChunk message and send it to the server response = stub.UploadFile(file_upload_pb2.FileChunk(data=chunk)) print(f"Upload status: {response.success}") def read_in_chunks(file, chunk_size=1024): while True: data = file.read(chunk_size) if not data: break yield file_upload_pb2.FileChunk(data=data) if __name__ == '__main__': channel = grpc.insecure_channel('localhost:50051') stub = file_upload_pb2_grpc.FileUploadServiceStub(channel) upload_file(stub, 'path/to/your/file.txt') ``` -------------------------------- ### Example Protocol Buffer Definition for User Service Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/proto-generation.rst This Protocol Buffer definition outlines a gRPC service for user management, including standard CRUD operations (List, Create, Retrieve, Update, Destroy) and a custom method. It also defines the corresponding message structures for requests and responses, demonstrating typical gRPC service and message declarations. ```proto syntax = "proto3"; package doc_example.generate_proto_doc; import "google/protobuf/empty.proto"; service UserController { rpc List(UserListRequest) returns (UserListResponse) {} rpc Create(UserRequest) returns (UserResponse) {} rpc Retrieve(UserRetrieveRequest) returns (UserResponse) {} rpc Update(UserRequest) returns (UserResponse) {} rpc Destroy(UserDestroyRequest) returns (google.protobuf.Empty) {} rpc SomeCustomMethod(SomeCustomMethodRequest) returns (stream SomeCustomMethodResponse) {} } message UserResponse { string id = 1; string full_name = 2; } message UserListRequest { } message UserListResponse { repeated UserResponse results = 1; } message UserRequest { string id = 1; string full_name = 2; } message UserRetrieveRequest { string id = 1; } message UserDestroyRequest { string id = 1; } message SomeCustomMethodRequest { string foo = 1; } message SomeCustomMethodResponse { string bar = 1; } ``` -------------------------------- ### Define gRPC Service and Generate Proto with django-socio-grpc Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/grpc-action.rst This example demonstrates how to create an asynchronous gRPC service using `django-socio-grpc`'s `AsyncModelService` and `grpc_action` decorator in Python. It shows how to define custom request and response message types, and the corresponding Protocol Buffer (.proto) code that is automatically generated by the `generateproto` command. ```python # service.py from django_socio_grpc.decorators import grpc_action from django_socio_grpc.generics import AsyncModelService from my_app.models import MyModel # Replace by your model from my_app.serializers import MyModelProtoSerializer # Replace by your serializer class MyModelService(AsyncModelService): queryset = MyModel.objects.all().order_by("uuid") serializer_class = MyModelProtoSerializer @grpc_action( request=[{"name": "my_example_request", "type": "string"}], response=[{"name": "my_example_response", "type": "string"}], ) async def Retrieve(self, request, context): pass ``` ```proto import "google/protobuf/empty.proto"; service MyModelController { ... rpc Retrieve(ExampleRetrieveRequest) returns (ExampleRetrieveResponse) {} ... } ... message ExampleRetrieveRequest { string my_example_request = 1; } message ExampleRetrieveResponse { string my_example_response = 1; } ``` -------------------------------- ### Apply Placeholders in Django Socio gRPC Service Actions Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/grpc-action.rst This example illustrates how to integrate custom and predefined placeholders within the `@grpc_action` decorator in `django-socio-grpc` services. It shows how placeholders like `AttrPlaceholder` and `RequestNamePlaceholder` dynamically determine request/response parameters and names for gRPC methods, enabling flexible service inheritance and proto generation. ```python # service.py from django_socio_grpc.generics import GenericService from django_socio_grpc.grpc_actions.placeholders import AttrPlaceholder, SelfSerializer class ExampleSuperService(GenericService): @grpc_action( request=AttrPlaceholder("_request"), request_name=RequestNamePlaceholder, # RequestNamePlaceholder comes from the doc code just above response=SelfSerializer, response_name = "MyResponse", ) def Route(self, request, context): ... class ExampleSubService(ExampleSuperService): serializer_class = MySerializer _request = [] def Route(self, request, context): ... ``` -------------------------------- ### Set gRPC Server Options for Message Size Limits Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/settings.rst This setting defines key-value pairs to configure gRPC server behavior, such as setting limits on message sizes. The example configures the server to allow sending and receiving messages up to 100MB. ```python "SERVER_OPTIONS": [ ("grpc.max_send_message_length", 100 * 1024 * 1024), ("grpc.max_receive_message_length", 100 * 1024 * 1024) ], ``` -------------------------------- ### Define gRPC service with exception handling for logging Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/logging.rst This Python code defines a `SomethingService` class with two gRPC actions. `RaiseUncaughtException` raises a `ValueError`, demonstrating an uncaught exception. `RaiseGrpcException` raises a `NotFound` exception, which is a `GRPCException` subclass. This setup illustrates how `django_socio_grpc.request` logs different exception types. ```python from django_socio_grpc.exceptions import NotFound class SomethingService(Service): @grpc_action(request=[], response=[]) async def RaiseUncaughtException(self, request, context): raise ValueError("test log") @grpc_action(request=[], response=[]) async def RaiseGrpcException(self, request, context): raise NotFound("test log") ``` -------------------------------- ### FakeFullAIOGRPC Class Reference for Django Socio gRPC Testing Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/testing.rst Documentation for `FakeFullAIOGRPC`, a crucial class in Django Socio gRPC for asynchronous testing of gRPC services. It facilitates the creation of a mock gRPC server, allowing direct function calls to service methods, thereby replacing actual network interactions. This class is the recommended approach for asynchronous test environments. ```APIDOC FakeFullAIOGRPC(add_servicer_to_server_func, servicer_instance) - Description: Initializes a mock gRPC server for testing Django Socio gRPC services. This class is designed for asynchronous contexts and replaces deprecated `FakeAIOGRPC` and `FakeGRPC`. - Parameters: - add_servicer_to_server_func: (function) A gRPC-generated function (e.g., `add_PostControllerServicer_to_server`) responsible for adding a servicer to a gRPC server. - servicer_instance: (object) The actual service instance (e.g., `PostService.as_servicer()`) that contains the logic for handling client RPC requests. - Returns: An instance of `FakeFullAIOGRPC` configured with the mock server. - Usage: When an instance is created, it sets up a mock gRPC server, enabling direct calls to your servicer methods as if they were being handled by a real gRPC server. ``` -------------------------------- ### Modern Client-side Filtering with Protobuf Structs in JavaScript Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/filters.rst This example illustrates the recommended way to apply filters from a JavaScript gRPC client using `@bufbuild/protobuf`'s `Struct.fromJson`. It demonstrates how to pass complex filter objects, which are transformed to the `Filters` field in the protobuf request, enabling flexible data querying. ```javascript import { Struct } from "@bufbuild/protobuf"; // See web usage to understand how to use the client. const postClient = createPromiseClient(PostController, transport); // filters only the user with id 1 const filtersStruct = Struct.fromJson({user: 1}); const res = await postClient.list({ Filters: filtersStruct }); // _filters is transformed to Filters in buf build used by connect console.log(res) // filters only the users with username containing "test-user" const filtersStruct = Struct.fromJson({search: "test-user"}); const res = await postClient.list({ Filters: filtersStruct }); // _filters is transformed to Filters in buf build used by connect console.log(res) ``` -------------------------------- ### Define Django Models for Bibliographic Service Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/examples/async-advanced-bib-example.rst This Python code defines the Django models for a bibliographic service. It includes `Author`, `Publisher`, and `Book` models, demonstrating UUID primary keys, various field types (CharField, DateField, URLField), ForeignKey relationships, and ManyToMany relationships, which are essential for the service's data structure. ```python from django.db import models # Author class class Author(models.Model): author_id = models.UUIDField(primary_key=True) name_first = models.CharField(max_length=100) name_last = models.CharField(max_length=100) birth_date = models.DateField() class Publisher(models.Model): publisher_id = models.UUIDField(primary_key=True) name = models.CharField(max_length=100) address = models.CharField(max_length=100) city = models.CharField(max_length=100) state_province = models.CharField(max_length=100) country = models.CharField(max_length=100) website = models.URLField() class Book(models.Model): book_id = models.UUIDField(primary_key=True) title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) isbn = models.CharField(max_length=20) publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) publication_date = models.DateField() ``` -------------------------------- ### Implement Custom GRPCActionBasePermission for Granular Access Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/authentication-permissions.rst This snippet provides an example of creating a custom permission class, `OnlySafeOrAdminOrOwner`, by inheriting from `GRPCActionBasePermission`. It demonstrates overriding `has_permission` and `has_object_permission` methods to implement complex access logic based on gRPC context, service, and object attributes, including handling safe methods and user roles. ```python from django_socio_grpc.permissions import GRPCActionBasePermission from django_socio_grpc.generics import AsyncModelService from rest_framework.permissions import SAFE_METHODS class OnlySafeOrAdminOrOwner(GRPCActionBasePermission): def has_permission(self, context, service): if self.context.method in SAFE_METHODS: return True if context.grpc_action == "SomeCustomSafeEndpoint": return True return context.user.is_superuser def has_object_permission(self, context, service, obj): if self.context.method in SAFE_METHODS: return True if str(obj.created_by) == str(request.user.pk): return True return context.user.is_superuser class ExampleService(AsyncModelService): permission_classes = [OnlySafeOrAdminOrOwner] ``` -------------------------------- ### Django Socio gRPC Management Commands Reference Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/commands.rst Comprehensive reference for the `manage.py` commands provided by Django Socio gRPC. This includes the `generateproto` command for creating protocol buffer files and the `grpcrunaioserver` and `grpcrunserver` commands for launching gRPC servers in asynchronous and synchronous modes, respectively. Each command's purpose, parameters, and usage notes are detailed. ```APIDOC manage.py generateproto [--project PROJECT] [--dry-run] [--no-generate-pb2] [--check] [--custom-verbose VERBOSE_LEVEL] [--directory DIRECTORY] - Description: Generates .proto files from Django models and services. - Parameters: - --project: Specifies the Django project. Uses DJANGO_SETTINGS_MODULE by default. - --dry-run: Prints proto data to console without writing files. - --no-generate-pb2: Prevents generation of PB2 Python files. - --check: Returns an error if the generated file differs from an existing one. - --custom-verbose: Integer from 1 to 4, sets the verbose level of generation. - --directory: Specifies the output directory for proto files. Defaults to app directories. manage.py grpcrunaioserver [address] [--max-workers MAX_WORKERS] [--dev] - Description: Launches the asynchronous gRPC I/O server. This is the recommended way to run gRPC services in production. - Parameters: - address: Optional address for which to open a port. - --max-workers: Number of maximum worker threads. Only needed for migration from sync to async server; has no effect if server is fully async. - --dev: Runs the server in development mode, enabling Django's auto-reloader and checks. manage.py grpcrunserver - Description: Launches the synchronous gRPC server. This command is similar to `grpcrunaioserver` but for synchronous mode. It is provided for convenience for local testing and is not recommended for production use; it will be removed in the future. - Parameters: - Note: The `--max-workers` argument has no effect with this command. ``` -------------------------------- ### gRPC-Web Protocol Buffer Compiler Plugins and Import Styles Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/grpc-web.rst This documentation outlines the various `protoc` plugins available for generating client code from `.proto` files specifically for browser environments. It details each plugin's source and the different JavaScript/TypeScript import styles they support, crucial for compatibility with modern frontend build tools like Vite. ```APIDOC 1. protoc-gen-grpc-web: - Source: Directly available on the gRPC-Web release page. - Supported Import Styles: closure, commonjs, commonjs+dts, typescript. - Reference: https://github.com/grpc/grpc-web#code-generator-plugin 2. protobuf-javascript: - Source: The official Protocol Buffers open-source project for compiling to JavaScript. - Supported Import Styles: Closure, commonjs. - Reference: https://github.com/protocolbuffers/protobuf-javascript 3. BUF cli with @connectrpc/protoc-gen-connect-es: - Description: A BUF plugin specifically designed for generating gRPC Service definitions. - Supported Import Styles: ESM (ECMAScript Modules), compatible with both JavaScript and TypeScript. - Reference: https://github.com/connectrpc/connect-es 4. BUF cli with @bufbuild/protoc-gen-es: - Description: A BUF plugin used for generating request and message types. - Supported Import Styles: ESM (ECMAScript Modules), compatible with both JavaScript and TypeScript. - Reference: https://github.com/bufbuild/protobuf-es Note on Vite Compatibility: - Vite does not support CommonJS modules as it prioritizes ESM for faster JavaScript compilation. Refer to: https://github.com/grpc/grpc-web/issues/1242 ``` -------------------------------- ### Compile Protobuf Files to Python using Docker Compose Source: https://github.com/socotecio/django-socio-grpc/blob/master/django_socio_grpc/tests/fakeapp/README.md This command compiles a Protobuf file (`unittest.proto`) into Python source files (`_pb2.py` and `_pb2_grpc.py`) using `grpc_tools.protoc` within a `django-socio-grpc` Docker container. It provides two options: `docker compose run` for a new container or `docker compose exec` if the container is already running, ensuring the necessary Python gRPC bindings are generated for testing. ```shell docker compose run django-socio-grpc python -m grpc_tools.protoc --proto_path=./ --python_out=./ --grpc_python_out=./ ./django_socio_grpc/tests/grpc_test_utils/unittest.proto # or if docker already run docker compose exec django-socio-grpc python -m grpc_tools.protoc --proto_path=./ --python_out=./ --grpc_python_out=./ ./django_socio_grpc/tests/grpc_test_utils/unittest.proto ``` -------------------------------- ### Raising and Catching Built-in gRPC Exceptions in DSG Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/exceptions.rst This example demonstrates how to raise a built-in `InvalidArgument` exception on the server-side within a Django-Socio-gRPC service and how to catch and inspect the resulting `grpc.RpcError` on the client-side, extracting its code and details. ```python # server from django_socio_grpc.exceptions import InvalidArgument class RaiseCustomErrorService(GenericService): @grpc_action() async def RaiseError(self, request, context): raise InvalidArgument() # client import asyncio import grpc async def main(): async with grpc.aio.insecure_channel("localhost:50051") as channel: my_app_client = my_app_pb2_grpc.RaiseCustomErrorControllerStub(channel) request = my_app_pb2.RaiseErrorRequest() try: await my_app_client.RaiseError(request) except grpc.RpcError as e: print(e.code()) print(e.details()) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Define a Django Post Model Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/proto-serializers.rst Defines a simple Django model named `Post` with fields like `pub_date`, `headline`, `content`, and a `ForeignKey` to `User`. This model serves as the base for `ModelProtoSerializer` examples. ```python 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) ``` -------------------------------- ### Declare Filter Fields Using filterset_fields in Django-Socio-gRPC Service Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/filters.rst This example demonstrates how to define filterable fields directly on a `django-socio-grpc` service using the `filterset_fields` attribute. This method is straightforward for specifying which model fields can be used for basic filtering operations. ```python # server # quickstart/services.py from django_socio_grpc import generics from django_filters.rest_framework import DjangoFilterBackend from quickstart.models import Post from quickstart.serializer import PostProtoSerializer # This service will have all the CRUD actions class PostService(generics.AsyncModelService): queryset = Post.objects.all() serializer_class = PostProtoSerializer filter_backends = [DjangoFilterBackend] filterset_fields = ['user'] ``` -------------------------------- ### Basic gRPC RPC Definition in Proto Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/grpc-action.rst Illustrates a basic Remote Procedure Call (RPC) definition in a `.proto` file, showing the service method name, its request message type, and its response message type. This structure is automatically generated by Django-Socio-gRPC's `grpc_action` decorator. ```proto rpc BasicList(BasicRequest) returns (BasicResponse) {} ``` -------------------------------- ### Istio VirtualService CORS Policy for gRPC-web Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/how-to/grpc-web.rst Example YAML configuration for an Istio VirtualService, specifically setting the `corsPolicy` to enable cross-origin requests required by gRPC-web and Django Socio gRPC. This ensures proper communication between client and server in a production environment. ```yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: ... labels: ... spec: hosts: ... gateways: ... http: - match: ... route: ... corsPolicy: ``` -------------------------------- ### Generate Protobufs for FakeApp using Docker Compose Source: https://github.com/socotecio/django-socio-grpc/blob/master/django_socio_grpc/tests/fakeapp/README.md This command executes a Python script (`test_utils/generateproto.py`) inside the `django-socio-grpc` Docker container. Its purpose is to generate Protobuf files specifically for the 'FakeApp' test application, which is crucial for setting up and running integration tests within the project's development environment. ```shell docker compose exec django-socio-grpc python test_utils/generateproto.py ``` -------------------------------- ### Django generateproto Command Options Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/features/proto-generation.rst Detailed options available for the `python manage.py generateproto` command, allowing control over the generation process, including project naming, output behavior, verbosity, and file generation specifics. ```APIDOC generateproto Command Options: --project (-p) Description: Name of the Django project that is used in the proto package name. Default: Uses DJANGO_SETTINGS_MODULE first folder. --dry-run (-dr) Description: Prints the protofile content to the terminal without writing it to a file or generating new Python code. Default: False --no-generate-pb2 (-nopb2) Description: Avoids generating the Python file (pb2.py), only generating the .proto file. Default: False --check (-c) Description: Checks if the current protofile is identical to the one that would be generated by a new command, ensuring API synchronization with models. Default: False --custom-verbose (-cv) Description: Sets the verbose level of the generation process, from 1 to 4. Default: 0 --directory (-d) Description: Specifies the directory where the proto files will be generated. If not specified, defaults to the apps directories. Default: None --override-fields-number (-ofn) Description: Disables following old field numbers when generating. WARNING: This can lead to API breaking changes. Default: False --extra-args (-a) Description: Adds extra arguments to the underlying protoc command (e.g., `generateproto -a --mypy_out=./ --mypy_grpc_out=./`). Default: None ``` -------------------------------- ### Define Default Pagination Class for gRPC Services Source: https://github.com/socotecio/django-socio-grpc/blob/master/docs/settings.rst This setting defines the default pagination class for gRPC services. This class will be used to paginate large datasets in the response, ensuring efficient data transfer. An example configuration uses DRF's `PageNumberPagination` class. ```python "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination" ```