Channels Binding API
Channels Binding exposes an JSON API streaming system over channels, It’s designed to work as a full featured RestAPI via websocket, http, or both protocols combined. in very few code lines, with a very simple and verboseless exchange structure, where each django Models would be easily binded and come with native basics operations like ‘retrieve’, ‘search’, ‘update’, ‘create’, ‘delete’ and subscription. We could made the comparaison with django restframework with the REST system. It also provides react packages with ready-to-use pre configured tools and components to make easy Applications UIs.
Channels-binding is a compilation of somes packages :
https://pypi.org/project/channels-binding/ for python/django
https://www.npmjs.com/package/@channels-binding/core for node/react
https://www.npmjs.com/package/@channels-binding/mui for material-ui integration
Summary
Capabilities
Support of ‘retrieve’, ‘form’, ‘search’, ‘list’’update’, ‘create’, ‘save’, ‘delete’, ‘subscribe’ events
Support of django signals to refresh any connected instance with React tools
Support of native django Queryset into React (Material-UI Tables available)
Support of native django Form into React (Material-UI Fields available)
Support of Hashed events for targeted subscribers (example: 2 lists on the same stream/event/model but with different filtering)
Auto channels subscribing groups of interest ‘retrieve’, ‘list’, ‘delete’
Custom bindings events through decorators
Compatible with Django restframework serializers (soon ready)
Both Async or Sync Consumers (not yet)
Both HTTP Rest or WS API (not yet)
Exchanges Structure Overviews
SELF SEND => {
event: "auth.User.search",
data: {
page: 2
}
}
SELF RECEIVE => {
event: "auth.User.search",
data: {
page: 2,
limit: 25,
count: 102,
rows: [{
id: 5763,
username: "Admin",
email: "admin@admin.com"
}, ... ]
}
}
SELF SEND => {
event: "auth.User.retrieve",
data: {
id: 5763
}
}
SELF RECEIVE => {
event: "auth.User.retrieve",
data: {
id: 5763,
username: "Admin",
email: "admin@admin.com",
...andMoreDetails
}
}
SELF SEND => {
event: "auth.User.update",
data: {
id: 5763,
username: "Changed Username"
}
}
SELF RECEIVE => {
event: "auth.User.update",
data: {
success: true
}
}
GROUP RECEIVE => {
event: "auth.User.retrieve",
data: {
id: 5763,
username: "Changed Username",
email: "admin@admin.com",
...andMoreDetails
}
}
Getting Started
Assume that you have already django>=1.8 and channels>=2.0.0 installed
Add channels-binding to requirements.txt
pip install channels-binding
Add channels_binding to INSTALLED_APPS
INSTALLED_APPS = (
'channels',
'channels_binding',
)
Configure some optionnals SETTINGS
CHANNEL_LAYERS = {
'default': {
# ...someChannelsConfig
},
}
CHANNELS_BINDING = {
"AUTHENTIFICATION_CLASSES": (
'authentification.AuthenticationStrategyClass',
),
"DEFAULT_PAGE_SIZE": 25,
"ANONYMOUS_CONNECTION_ALLOWED": False, # Reject connection of non connected users
}
Add a new AsyncConsumer in your asgi application routing (Read the channels docs)
# asgi.py
from django.urls import path
from channels.sessions import SessionMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels_binding.consumers import AsyncConsumer
application = ProtocolTypeRouter({
'websocket': SessionMiddlewareStack(
URLRouter([
path('', AsyncConsumer, name="root"),
])
)
})
Add bindinds inside an app or root bindigns folder
# apps/your_app/bindings.py
from channels_binding.consumers import AsyncBinding
from .models import YourModel
'''
All bindings in apps/*/bindings.py or app/bindings/*.py are auto discovered, like models.py
'''
class YourModelBinding(AsyncBinding):
model = YourModel
# stream = by default '{app_name.model_name}' if model is set
# permission_class = by default None (may change in future)
# serializer_class = by default None (soon compatible with restframwork serializer)
# queryset = by default YourModel.objects.all()
# page_size = by default 25 rows for the 'search' and 'list' events
# post_save_retrieve = by default True, if is True, an instance post_save send the 'retrieve' event to all the stream subscribers
Let’s start to communicate with a simple retrieve action on a frontal javascript thirdparty
// Soon React example...
var ws = new WebSocket("ws://" + window.location.host + "/")
ws.onmessage = function(e){
console.log(e.data)
/*
Receive:
{
event: "your_app.YourModel.retrieve",
data: {
id: 5763,
...someData
}
}
*/
}
ws.send(JSON.stringify({
event: "your_app.YourModel.retrieve",
data: {
id: 5763
}
}))
React front integration
Assume that you have already react installed
npm install @channels-binding/core
For an integration with material-ui
npm install @channels-binding/mui
Custom Events Binding
Add a full custom binding with
# apps/your_app/bindings.py
from channels_binding.consumers import AsyncBinding, bind
class YourCustomBinding(AsyncBinding):
stream = 'custom_stream'
@bind('custom_event')
async def handle_custom_event(self, data):
sender = data['sender']
# Direct reflect the reponse to the current socket pipe
await self.reflect('custom_event', {
'msg': f'This a reflected response for {sender}'
})
# Send an event to this stream subscribers
await self.dispatch('custom_group_event', {
'msg': f'This a dispatched response to the custom_stream subscriber from {sender}'
})
# Send an event to this stream subscribers
await self.broadcast('custom_all_event', {
'msg': f'This a dispatched response to the all layers from {sender}'
})
Let’s try this on a frontal javascript thirdparty
var ws = new WebSocket("ws://" + window.location.host + "/")
ws.onmessage = function(e){
console.log(e.data)
/*
Receive (reflected):
{
event: "custom_stream.custom_event",
data: {
msg: 'This a reflected response for me!!!'
}
}
Receive (from group to all "custom_stream" subscribers):
{
event: "custom_stream.custom_group_event",
data: {
msg: 'This a dispatched response to the custom_stream subscriber from me!!!'
}
}
Receive (broadcasted to all):
{
event: "custom_stream.custom_all_event",
data: {
msg: 'This a dispatched response to the all layers from me!!!'
}
}
*/
}
ws.send(JSON.stringify({
event: "custom_stream.custom_event",
data: {
sender: 'me!!!'
}
}))
Metadata
Release files for channels-binding 1.9.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| channels_binding-1.9.8.tar.gz | 20.2 kB | Without provenance | Details for channels_binding-1.9.8.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| channels_binding-1.9.8-py3-none-any.whl | Python 3 | none | any | Details for channels_binding-1.9.8-py3-none-any.whl |
Total release size: 50.7 kB
Release files / channels_binding-1.9.8.tar.gz
| Download URL | channels_binding-1.9.8.tar.gz |
|---|---|
| Size | 20.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d15980d8f81013469492c80d5188028a4c83d728f869d5cc7c55010e7e814915
|
|
BLAKE2b-256 checksum How to use checksums |
a62c5a8e8321920f81cd7c86ecbe5bcd6686596181101f8953dd2cb930d67c95
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.1 importlib_metadata/3.10.0 pkginfo/1.7.0 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.8.5
|
Release files / channels_binding-1.9.8-py3-none-any.whl
| Download URL | channels_binding-1.9.8-py3-none-any.whl |
|---|---|
| Size | 30.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7b50515df546b5b13643a359cbca9ee0d0bea4eca66dc95f409eec8f0f16c83c
|
|
BLAKE2b-256 checksum How to use checksums |
a2db62331644376e1956ea0b0201397f008a65bcffb9bbd660ccc0a658bfb54e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/3.4.1 importlib_metadata/3.10.0 pkginfo/1.7.0 requests/2.22.0 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.8.5
|
Security for channels-binding 1.9.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.