{"id":13625308,"url":"https://github.com/gluk-w/django-grpc","last_synced_at":"2025-05-16T18:08:55.322Z","repository":{"id":34038611,"uuid":"166471167","full_name":"gluk-w/django-grpc","owner":"gluk-w","description":"Easy gRPC service based on Django application","archived":false,"fork":false,"pushed_at":"2025-04-02T20:43:53.000Z","size":216,"stargazers_count":232,"open_issues_count":10,"forks_count":35,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-16T07:05:52.625Z","etag":null,"topics":["django","django-grpc","grpc","grpc-message","grpc-python","grpc-server","grpc-service","protobuf","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gluk-w.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-01-18T20:53:38.000Z","updated_at":"2025-03-21T14:07:38.000Z","dependencies_parsed_at":"2025-02-11T05:19:08.444Z","dependency_job_id":"920b495a-bd21-4c9c-b2c5-20a66aae49ef","html_url":"https://github.com/gluk-w/django-grpc","commit_stats":{"total_commits":55,"total_committers":11,"mean_commits":5.0,"dds":0.4363636363636364,"last_synced_commit":"a1eea990dca935387b50d721a1c3a5256ed3d7c8"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluk-w%2Fdjango-grpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluk-w%2Fdjango-grpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluk-w%2Fdjango-grpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gluk-w%2Fdjango-grpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gluk-w","download_url":"https://codeload.github.com/gluk-w/django-grpc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251347503,"owners_count":21575094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","django-grpc","grpc","grpc-message","grpc-python","grpc-server","grpc-service","protobuf","python"],"created_at":"2024-08-01T21:01:53.797Z","updated_at":"2025-04-28T16:40:14.255Z","avatar_url":"https://github.com/gluk-w.png","language":"Python","funding_links":[],"categories":["Python","Language-Specific"],"sub_categories":["Python"],"readme":"# django-grpc\n\nEasy way to launch gRPC server with access to Django ORM and other handy stuff.\ngRPC calls are much faster that traditional HTTP requests because communicate over\npersistent connection and are compressed. Underlying gRPC library is written in C which\nmakes it work faster than any RESTful framework where a lot of time is spent on serialization/deserialization.\n\nNote that you need this project only if you want to use Django functionality in gRPC service. \nFor pure python implementation [read this](https://grpc.io/docs/languages/python/quickstart/)\n\n* Supported Python: 3.10+\n* Supported Django: 4.2+\n\n## Installation\n\n```bash\npip install django-grpc\n``` \n\nUpdate settings.py\n```python\nINSTALLED_APPS = [\n    # ...\n    'django_grpc',\n]\n\nGRPCSERVER = {\n    'servicers': ['dotted.path.to.callback.eg.grpc_hook'],  # see `grpc_hook()` below\n    'interceptors': ['dotted.path.to.interceptor_class',],  # optional, interceprots are similar to middleware in Django\n    'maximum_concurrent_rpcs': None,\n    'options': [(\"grpc.max_receive_message_length\", 1024 * 1024 * 100)],  # optional, list of key-value pairs to configure the channel. The full list of available channel arguments: https://grpc.github.io/grpc/core/group__grpc__arg__keys.html\n    'credentials': [{\n        'private_key': 'private_key.pem',\n        'certificate_chain': 'certificate_chain.pem'\n    }],    # required only if SSL/TLS support is required to be enabled\n    'async': False  # Default: False, if True then gRPC server will start in ASYNC mode\n    'reflection': False, # Default: False, enables reflection on a gRPC Server (https://grpc.io/docs/guides/reflection/)\n}\n```\n\nThe callback that initializes \"servicer\" must look like following:\n```python\nimport my_pb2\nimport my_pb2_grpc\n\ndef grpc_hook(server):\n    my_pb2_grpc.add_MYServicer_to_server(MYServicer(), server)\n\n...\nclass MYServicer(my_pb2_grpc.MYServicer):\n\n    def GetPage(self, request, context):\n        response = my_pb2.PageResponse(title=\"Demo object\")\n        return response\n```\n\n## Usage\n```bash\npython manage.py grpcserver\n```\n\nFor developer's convenience add `--autoreload` flag during development.\n\n\n## Signals\nThe package uses Django signals to allow decoupled applications get notified when some actions occur:\n* `django_grpc.signals.grpc_request_started` - sent before gRPC server begins processing a request\n* `django_grpc.signals.grpc_request_finished` - sent when gRPC server finishes delivering response to the client\n* `django_grpc.signals.grpc_got_request_exception` - this signal is sent whenever RPC encounters an exception while\nprocessing an incoming request.\n\nNote that signal names are similar to Django's built-in signals, but have \"grpc_\" prefix.\n\n\n## Serializers\nThere is an easy way to serialize django model to gRPC message using `django_grpc.serializers.serialize_model`.\n\n## Helpers\n\n### Ratelimits\n\nYou can limit number of requests to your procedures by using decorator `django_grpc.helpers.ratelimit.ratelimit`.\n\n```python\nfrom tests.sampleapp import helloworld_pb2_grpc, helloworld_pb2\nfrom django_grpc.helpers import ratelimit\n\n\nclass Greeter(helloworld_pb2_grpc.GreeterServicer):\n    \n    @ratelimit(max_calls=10, time_period=60)\n    def SayHello(self, request, context):\n        return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)\n```\n\u003e When limit is reached for given time period decorator will abort with status `grpc.StatusCode.RESOURCE_EXHAUSTED`\n\nAs storage for state of calls [Django's cache framework](https://docs.djangoproject.com/en/4.0/topics/cache/#django-s-cache-framework)\nis used. By default `\"default\"` cache system is used but you can specify any other in settings `RATELIMIT_USE_CACHE`\n\n#### Advanced usage\n\nUsing groups\n```python\n@ratelimit(max_calls=10, time_period=60, group=\"main\")\ndef foo(request, context):\n    ...\n\n@ratelimit(max_calls=5, time_period=60, group=\"main\")\ndef bar(request, context):\n    ...\n```\n`foo` and `bar` will share the same counter because they are in the same group\n\nUsing keys\n```python\n@ratelimit(max_calls=5, time_period=10, keys=[\"request:dot.path.to.field\"])\n@ratelimit(max_calls=5, time_period=10, keys=[\"metadata:user-agent\"])\n@ratelimit(max_calls=5, time_period=10, keys=[lambda request, context: context.peer()])\n```\nRight now 3 type of keys are supported with prefixes `\"request:\"`, `\"metadata:\"` and as callable.\n\n- `\"request:\"` allows to extract request's field value by doted path\n- `\"metadata:\"` allows to extract metadata from `context.invocation_metadata()`\n- callable function that takes request and context and returns string\n\n\u003e NOTE: if value of key is empty string it still will be considered a valid value\n\u003e and can cause sharing of ratelimits between different RPCs in the same group\n\n\u003e TIP: To use the same configuration for different RPCs use dict variable\n\u003e ```python\n\u003e MAIN_GROUP = {\"max_calls\": 5, \"time_period\": 60, \"group\": \"main\"}\n\u003e \n\u003e @ratelimit(**MAIN_GROUP)\n\u003e def foo(request, context):\n\u003e    ...\n\u003e\n\u003e @ratelimit(**MAIN_GROUP)\n\u003e def bar(request, context):\n\u003e    ...\n\u003e ```\n\n\n## Testing\nTest your RPCs just like regular python methods which return some \nstructure or generator. You need to provide them with only 2 parameters:\nrequest (protobuf structure or generator) and context (use `FakeServicerContext` from the example below).\n\n### Fake Context\nYou can pass instance of `django_grpc_testtools.context.FakeServicerContext` to your gRPC method\nto verify how it works with context (aborts, metadata and etc.).\n```python\nimport grpc\nfrom django_grpc_testtools.context import FakeServicerContext\nfrom tests.sampleapp.servicer import Greeter\nfrom tests.sampleapp.helloworld_pb2 import HelloRequest\n\nservicer = Greeter()\ncontext = FakeServicerContext()\nrequest = HelloRequest(name='Tester')\n\n# To check metadata set by RPC \nresponse = servicer.SayHello(request, context)\nassert context.get_trailing_metadata(\"Header1\") == '...'\n\n# To check status code\ntry:\n    servicer.SayHello(request, context) \nexcept Exception:\n    pass\n\nassert context.abort_status == grpc.StatusCode.INVALID_ARGUMENT\nassert context.abort_message == 'Cannot say hello to John'\n```\n\nIn addition to standard gRPC context methods, FakeServicerContext provides:\n * `.set_invocation_metadata()` allows to simulate metadata from client to server.\n * `.get_trailing_metadata()` to get metadata set by your server\n * `.abort_status` and `.abort_message` to check if `.abort()` was called \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgluk-w%2Fdjango-grpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgluk-w%2Fdjango-grpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgluk-w%2Fdjango-grpc/lists"}