=============== LIBRARY RULES =============== From library maintainers: - Always use instance.save() - never Model.objects.update() as it bypasses signals - Serializers must be nested ModelSerializer instances - Channel files must be named channels.py for auto-discovery - Run makefrontend after serializer or channel changes - Authentication uses rest_framework.authtoken.models.Token only - ContextChannel.has_permission() is called once on connect to check access - Use @action decorator for RPC methods callable from frontend - Use @consumer decorator to subscribe to Django Channels groups ### Set Up WebSocket Routing for RxDjango Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/quickstart.md Configures the WebSocket URL patterns in the project's asgi.py file to route requests to the custom RxDjango ContextChannel. This enables the frontend to connect to the backend channel. ```python from myapp.channels import MyContextChannel websocket_urlpatterns = [ path('ws/myapp//', MyContextChannel.as_asgi()), ] application = ProtocolTypeRouter({ "http": app, "websocket": URLRouter( websocket_urlpatterns ), }) ``` -------------------------------- ### Install RxDjango Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Installs the RxDjango package using pip. This is the first step to integrate RxDjango into your Django project. ```bash pip install rxdjango ``` -------------------------------- ### Create RxDjango ContextChannel Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/quickstart.md Defines a custom ContextChannel by subclassing rxdjango.channels.ContextChannel. This channel is used to manage real-time state synchronization and defines metadata like the serializer and permissions. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() @staticmethod def has_permission(user, instance): # check if user has permission on instance return True ``` -------------------------------- ### Implement Search Action for List Channels (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Provides an example of an action method (`search`) for a list-based RxDjango channel. It demonstrates how to modify the channel's context by adding, removing, or clearing instances, enabling features like client-side search. ```python from rxdjango.actions import action class MyContextListChannel(ContextChannel): search_term = None @action async def search(self, term: str) -> None: self.search_term = term instances = self._list_instances() self.clear() for instance in instances: self.add_instance(instance) ``` -------------------------------- ### Install RxDjango React Frontend Package Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Installs the `@rxdjango/react` package on the frontend using yarn. This package provides the necessary hooks and components to integrate RxDjango channels with your React application. ```bash yarn add @rxdjango/react ``` -------------------------------- ### Generate Frontend Files with RxDjango Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/quickstart.md Generates frontend TypeScript interfaces and classes based on backend serializers using the `makefrontend` management command. This command can be run manually or automatically with `runserver --makefrontend`. ```bash python manage.py makefrontend ``` ```bash python manage.py runserver --makefrontend ``` -------------------------------- ### Connect Frontend State with RxDjango Channel Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/quickstart.md Connects the frontend state to a RxDjango ContextChannel using the `useChannelState` hook from `@rxdjango/react`. This establishes a real-time link between the frontend and backend state. ```typescript import { MyContextChannel } from 'app/modules/myapp.channels'; import { useChannelState } from '@rxdjango/react'; const channel = new MyContextChannel(mymodelId, token); const { state } = useChannelState(channel); ``` -------------------------------- ### Run Django Development Server with Automatic Frontend Generation Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Starts the Django development server using the `runserver` command with the `--makefrontend` option. This automatically regenerates frontend files whenever changes are detected, streamlining the development workflow. ```bash python manage.py runserver --makefrontend ``` -------------------------------- ### Use RxDjango Channel State in React Frontend (TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Example of integrating RxDjango channels into a React application using the `@rxdjango/react` library. It demonstrates how to instantiate a channel and use the `useChannelState` hook to access and react to real-time state updates. ```typescript import { useChannelState } from "@rxdjango/react"; import { MyNestedType } from "my-rx-frontend-dir/myapp.interfaces"; import { MyContextChannel } from "my-rx-frontend-dir/myapp.channels"; const MyPage = () => { const channel = new MyContextChannel(instanceId, auth.token); const { state } = useChannelState(channel); } ``` -------------------------------- ### Get Cache TTL Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Retrieve the cache Time To Live (TTL) in seconds for a channel. It checks Meta.cache_ttl, RX_CACHE_TTL setting, and defaults to 604800 seconds (1 week). ```python get_cache_ttl() -> int ``` -------------------------------- ### Get Registered Channels Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Return a set of all registered ContextChannel subclasses. Useful for introspection and cache management tooling. ```python get_registered_channels() -> set ``` -------------------------------- ### Schedule RxDjango Cache Expiration with Cron Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/caching.md This example shows how to schedule the `expire_rxdjango_cache` management command to run automatically at regular intervals using cron. This ensures that stale caches are periodically cleaned up without manual intervention. ```bash # cron - run every 5 minutes */5 * * * * cd /path/to/project && python manage.py expire_rxdjango_cache ``` -------------------------------- ### ContextChannel (Backend) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Documentation for the ContextChannel base class used for creating real-time channels in the backend. ```APIDOC ## ContextChannel (Backend) Base class for creating real-time channels. ### Class: ContextChannel Base class for defining a real-time data channel. Subclass this in a file named `channels.py` inside a Django app. #### Meta Options * **Meta.state** (*ModelSerializer*): The serializer defining the state structure. Can be a single serializer or `serializer(many=True)` for list states. * **Meta.auto_update** (*bool*, default: `False`): For `many=True` states, automatically add/remove instances when they match/unmatch the queryset. * **Meta.optimize_anchors** (*bool*, default: `False`): Add `_rx_*` boolean fields to models for efficient filtering. When enabled, the metaclass adds a `BooleanField` (with `db_index=True`) to the anchor model, allowing optimized queries for active channels. * **Meta.cache_ttl** (*int | None*, default: `None`): Per-channel TTL override in seconds. When set, this channel’s cache will expire after the specified duration instead of using the global `RX_CACHE_TTL` setting. Set to `None` (default) to use the global setting. ### Methods * **has_permission(user, **kwargs) → bool** Check if a user can access this channel. * **Parameters:** * `user` (The authenticated Django user) * `kwargs` (URL parameters from the WebSocket route) * **Returns:** `True` if access is allowed * **async is_visible(instance_id) → bool** For `many=True` channels, check if an instance should be visible to the connected user. * **Parameters:** * `instance_id` (The ID of the instance to check) * **async on_connect(tstamp)** Called after authentication succeeds. Use for initialization. * **Parameters:** * `tstamp` (Last known timestamp if reconnecting, or None) * **async on_disconnect()** Called when the WebSocket disconnects. Use for cleanup. * **get_instance_id(**kwargs) → int | str** Return the anchor instance ID from URL parameters. Override to customize how the anchor ID is extracted. * **Parameters:** * `kwargs` (URL parameters from the WebSocket route) * **async list_instances(**kwargs) → QuerySet** For `many=True` channels, return the queryset of anchor instances. Must be implemented by subclasses using `many=True`. * **async add_instance(instance_id, at_beginning=False)** Add an instance to a `many=True` channel’s list. * **Parameters:** * `instance_id` (ID of the instance to add) * `at_beginning` (If True, prepend to the list) * **async remove_instance(instance_id)** Remove an instance from a `many=True` channel’s list. * **Parameters:** * `instance_id` (ID of the instance to remove) * **async set_runtime_var(var, value)** Set a runtime variable and push it to the connected client. * **Parameters:** * `var` (Variable name) * `value` (Variable value (must be JSON-serializable)) * **async send(*args, **kwargs)** Proxy to the underlying `AsyncWebsocketConsumer.send()`. Use this to send arbitrary data to the connected client. * **async group_add(group)** Add this consumer to a Django Channels group. Use this in `on_connect()` to subscribe to group events handled by `@consumer` decorated methods. * **Parameters:** * `group` (The group name to join) * **async serialize_instance(instance, tstamp=0) → dict** Serialize a model instance using the channel’s state model. Returns a flat dictionary suitable for broadcasting. * **Parameters:** * `instance` (The Django model instance to serialize) * `tstamp` (Timestamp to attach to the serialized data) ``` -------------------------------- ### Configure Django INSTALLED_APPS for RxDjango Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Configures the INSTALLED_APPS setting in Django to include RxDjango, daphne, and channels. RxDjango must precede daphne, and both must precede django.contrib.staticfiles for correct operation. ```python INSTALLED_APPS = [ # rxdjango must come before daphne, and both before contrib.staticfiles 'rxdjango', 'daphne', 'django.contrib.staticfiles', # these can come anywhere 'channels', ] ``` -------------------------------- ### Define Single Instance Channel with Permissions Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Demonstrates how to create a single instance ContextChannel. It requires a Meta class with a serializer and implements the `has_permission` static method to control access to the channel's state, which is relayed as a dictionary. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() @staticmethod def has_permission(user, instance_id): # Check permission pass ``` -------------------------------- ### ContextChannel Methods Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Explains the various methods available on a ContextChannel instance for managing permissions, retrieving instances, and manipulating the channel's state. ```APIDOC ## ContextChannel Methods ### Description Provides an overview of the methods available on a `ContextChannel` instance for handling permissions, listing and manipulating channel instances, and controlling visibility. ### Method N/A (Instance Methods) ### Endpoint N/A (Instance Methods) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python # Example usage within a ContextChannel subclass class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer(many=True) @staticmethod def has_permission(user, instance_id): # Custom permission logic return True def list_instances(self): # Return a queryset of instances return MyModel.objects.all() def add_instance(self, instance_id, at_beginning=False): # Add an instance to the state pass def remove_instance(self, instance_id): # Remove an instance from the state pass def clear(self): # Clear all instances from the state pass def is_visible(self, instance): # Check if an instance should be visible return True ``` ### Response #### Success Response (200) N/A (Method Descriptions) #### Response Example N/A (Method Descriptions) ``` -------------------------------- ### RxDjango Multiple Instance Channel with List Method (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Shows how to create a ContextChannel for multiple instances by setting `many=True` in the Meta.state serializer. It requires implementing the `list_instances` method to return a queryset or list of instance IDs, potentially using `@database_sync_to_async`. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer from mayapp.models import MyModel() class MyContextListChannel(ContextChannel): class Meta: state = MyNestedSerializer(many=True) async def list_instances(self, **kwargs): # Return a queryset of visible objects # You may need to use @database_sync_to_async ``` -------------------------------- ### Expose Frontend RPC Action Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Expose an asynchronous ContextChannel method as a frontend-callable RPC action. Supports automatic parameter serialization and type hint inspection for conversions (e.g., datetime strings to datetime objects). ```python @action async def update_status(self, status: str) -> dict: self.instance.status = status self.instance.save() return {"success": True} ``` -------------------------------- ### Override RxDjango Cache TTL for a Specific Channel Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/caching.md This example shows how to override the global RxDjango cache TTL for a specific channel by defining `cache_ttl` within the channel's `Meta` class. This allows for granular control over cache expiry durations on a per-channel basis. ```python # channels.py from rxdjango.channels import ContextChannel from .serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() cache_ttl = 3600 # Override: 1 hour for this channel ``` -------------------------------- ### Define Multiple Instance Channel with Queryset Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Illustrates the creation of a multiple instance ContextChannel. The Meta class specifies `many=True` in the serializer, and the `list_instances` method must return a queryset to provide the list of dictionaries representing the channel's state. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer(many=True) def list_instances(self): # Filter objects user can see, hypothetically return MyModel.objects.filter(user=self.user) ``` -------------------------------- ### Frontend API - ContextChannel Class Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Documentation for the ContextChannel class, which manages WebSocket connections, authentication, state rebuilding, and RPC calls. ```APIDOC ## Frontend API - ContextChannel Class ### Description Base class for generated TypeScript channel classes. Manages WebSocket connection, authentication, state rebuilding, and RPC. ### Class Definition `ContextChannel()` * **Arguments:** * **T** – Type of the root/anchor state * **Y** – Type of the runtime state (optional) ### Constructor `constructor(token)` * **Arguments:** * **token** – Django REST Framework auth token ### `init()` Initializes the WebSocket and StateBuilder. Called automatically on first `subscribe()`. ### `disconnect()` Gracefully closes the WebSocket connection. ### `subscribe(listener, noConnectionListener?)` Subscribes to state changes. Auto-connects on the first subscriber. * **Arguments:** * **listener** – Callback invoked with new state on every update * **noConnectionListener** – Optional callback for connection status * **Returns:** Unsubscribe function ### `subscribeInstance(listener, instance_id, instance_type)` Subscribes to changes on a specific instance. * **Arguments:** * **listener** – Callback invoked when instance changes * **instance_id** – The instance ID * **instance_type** – The `_instance_type` string * **Returns:** Unsubscribe function ### `getInstance(instance_type, instance_id)` Retrieves a specific instance from the state. * **Arguments:** * **instance_type** – The `_instance_type` string * **instance_id** – The instance ID * **Returns:** The instance, or null if not found. ### `callAction(action, params)` Calls a backend `@action` method via WebSocket RPC. Used internally by generated subclass methods. * **Arguments:** * **action** – The snake_case action name * **params** – Array of parameters * **Returns:** Promise resolving with the action’s return value. ``` -------------------------------- ### Serializer Meta Options for Real-time Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Configure real-time behavior for DRF serializers using extended Meta options. Includes `user_key` for user-specific broadcasts, `optimistic` for immediate frontend updates, and `optimistic_timeout` to control server override duration. ```python class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = ['id', 'title', 'owner'] user_key = 'owner' optimistic = True optimistic_timeout = 3 ``` -------------------------------- ### Class Methods Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Class methods for broadcasting updates and managing channel state. ```APIDOC ## Class Methods ### broadcast_instance #### Description Manually broadcasts an instance update to all connected clients for a given anchor. #### Method `classmethod broadcast_instance(cls, anchor_id, instance, operation='update')` #### Parameters - **anchor_id** (str) - Required - The ID of the anchor. - **instance** (Model) - Required - The model instance to broadcast. - **operation** (str) - Optional - The type of operation ('create', 'update', or 'delete'). Defaults to 'update'. ### broadcast_notification #### Description Sends a notification to connected clients for a given anchor. If `user_id` is provided, the notification is sent only to that user. #### Method `classmethod broadcast_notification(cls, anchor_id, notification_data, user_id=None)` #### Parameters - **anchor_id** (str) - Required - The ID of the anchor. - **notification_data** (dict) - Required - The notification payload. - **user_id** (str) - Optional - The ID of the user to send the notification to. ### get_cache_ttl #### Description Returns the cache TTL in seconds for this channel. It checks `Meta.cache_ttl` first, then the global `RX_CACHE_TTL` setting, defaulting to 1 week. #### Method `classmethod get_cache_ttl(cls)` #### Response - **ttl** (int) - The cache time-to-live in seconds. ### get_registered_channels #### Description Returns the set of all registered ContextChannel subclasses. #### Method `classmethod get_registered_channels(cls)` #### Response - **channels** (set) - A set of registered ContextChannel subclasses. ### runtime_state #### Description This property is a dictionary containing the runtime state of the application. It should be updated using the `set_runtime_var` method so changes are relayed to the frontend. #### Property `runtime_state` (dict) ### set_runtime_var #### Description Sets one runtime variable, which will be relayed to the frontend and updated there. #### Method `classmethod set_runtime_var(cls, key, value)` #### Parameters - **key** (str) - Required - The key of the runtime variable. - **value** (any) - Required - The value of the runtime variable. ``` -------------------------------- ### ContextChannel - Multiple Instances Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Defines a multiple instance channel where the state relayed to the frontend is a list of dictionaries. Requires implementation of the `list_instances` method. ```APIDOC ## ContextChannel - Multiple Instances ### Description Represents a multiple instances channel. The state for this channel is a list of dictionaries. Requires the implementation of the `list_instances` method to provide a queryset of objects. ### Method N/A (Class Definition) ### Endpoint N/A (Class Definition) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer from myapp.models import MyModel class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer(many=True) def list_instances(self): # Filter objects user can see, hypothetically return MyModel.objects.filter(user=self.user) ``` ### Response #### Success Response (200) - **state** (list) - A list of dictionaries, where each dictionary represents an instance. #### Response Example ```json { "state": [ { "id": 1, "name": "Instance 1" }, { "id": 2, "name": "Instance 2" } ] } ``` ``` -------------------------------- ### ContextChannel Meta Class Options Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Details the configuration options available within the Meta class of a ContextChannel, including state serialization, automatic updates, anchor optimization, and cache TTL. ```APIDOC ## ContextChannel Meta Class Options ### Description Configuration options for a ContextChannel, defined within its inner `Meta` class. These options control serialization, automatic updates, performance optimizations, and caching behavior. ### Method N/A (Class Definition) ### Endpoint N/A (Class Definition) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer(many=True) # Serializer for the state auto_update = True # Automatically add new instances optimize_anchors = True # Optimize anchor queries cache_ttl = 3600 # Cache time-to-live in seconds ``` ### Response #### Success Response (200) N/A (Configuration Options) #### Response Example N/A (Configuration Options) ``` -------------------------------- ### Serializer Meta Options Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Extended Meta options for DRF serializers to control real-time behavior. ```APIDOC ## Serializer Meta Options RxDjango extends the standard DRF serializer `Meta` with additional options that control real-time behavior for individual serializer layers. ### user_key #### Description Field name that identifies the owning user. When set, instances are only sent to the WebSocket client whose user matches this field value. #### Meta Option `user_key` (str) #### Example ```python class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = ['id', 'title', 'owner'] user_key = 'owner' ``` ### optimistic #### Description Enables optimistic updates. When `True`, the frontend can immediately reflect changes before server confirmation. Defaults to `False`. #### Meta Option `optimistic` (bool) ### optimistic_timeout #### Description Seconds before the server state overrides optimistic updates. Defaults to `3`. #### Meta Option `optimistic_timeout` (int) ``` -------------------------------- ### ContextChannel - Single Instance Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Defines a single instance channel where the state relayed to the frontend is a dictionary. Requires implementation of the `has_permission` static method. ```APIDOC ## ContextChannel - Single Instance ### Description Represents a single instance channel. The state for this channel is a dictionary, and it requires the implementation of the `has_permission` static method to control access. ### Method N/A (Class Definition) ### Endpoint N/A (Class Definition) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() @staticmethod def has_permission(user, instance_id): # Check permission return True ``` ### Response #### Success Response (200) - **state** (dict) - The state dictionary for the single instance. #### Response Example ```json { "state": { "field1": "value1", "field2": 123 } } ``` ``` -------------------------------- ### Frontend API - React Hooks Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Documentation for React hooks used to interact with the WebSocket channels. ```APIDOC ## Frontend API - React Hooks ### `useChannelState(channel)` React hook for subscribing to channel state. * **Arguments:** * **channel** – A `ContextChannel` instance, or undefined. * **Returns:** Object with `state`, `connected`, `no_connection_since`, `runtimeState`, `empty`, and `error` fields. ### `useChannelInstance(channel, instance_type, instance_id)` React hook for subscribing to a specific instance. * **Arguments:** * **channel** – A `ContextChannel` instance, or undefined. * **instance_type** – The `_instance_type` string. * **instance_id** – The instance ID, or undefined. * **Returns:** The instance, or null if not available. ``` -------------------------------- ### Generate Frontend Files Command Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Generates TypeScript interfaces and channel classes from Django serializers and ContextChannel subclasses. This command helps maintain consistency between backend and frontend code. Options include dry-run for previewing changes and force for rebuilding all files. ```bash python manage.py makefrontend python manage.py makefrontend --dry-run python manage.py makefrontend --force ``` -------------------------------- ### Consumer Methods Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Methods for managing WebSocket connections and communication within a consumer. ```APIDOC ## Consumer Methods ### on_connect #### Description This method is called after a user has been authenticated. It receives the timestamp of the last update this client had, in case this is a reconnection. Currently, the timestamp is always None from the client side. #### Method `async def on_connect(self, tstamp)` ### on_disconnect #### Description This method is called when the client disconnects. #### Method `async def on_disconnect(self, close_code)` ### group_add #### Description Adds the consumer to a Django Channels group. This should be called in `on_connect()` to subscribe to events handled by `@consumer` decorated methods. #### Method `async def group_add(self, group_name)` #### Parameters - **group_name** (str) - Required - The name of the group to join. #### Request Example ```python await self.group_add('my_group') ``` ### send #### Description Proxies to the underlying `AsyncWebsocketConsumer.send()`. Use this to send arbitrary JSON data to the connected client. #### Method `async def send(self, data)` #### Parameters - **data** (dict) - Required - The JSON data to send. ### serialize_instance #### Description Serializes a model instance using the channel's state model. Returns a flat dictionary suitable for broadcasting. This is an async method that wraps the state model's synchronous serialization in `database_sync_to_async`. #### Method `async def serialize_instance(self, instance)` #### Parameters - **instance** (Model) - Required - The model instance to serialize. #### Response - **serialized_data** (dict) - A flat dictionary representing the serialized model instance. ### clear_cache #### Description Clears the cache for a given anchor via the COOLING state. Returns `True` if the cache was cleared, `False` if the anchor was not in the HOT state. #### Method `classmethod clear_cache(cls, anchor_id)` #### Parameters - **anchor_id** (str) - Required - The ID of the anchor whose cache should be cleared. #### Response - **cleared** (bool) - `True` if the cache was cleared, `False` otherwise. ``` -------------------------------- ### Generate Frontend Code with RxDjango CLI (Bash) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Command-line instruction to generate TypeScript interfaces and classes for the frontend based on the backend RxDjango channel definitions. Requires `settings.RX_FRONTEND_DIR` and `settings.RX_WEBSOCKET_URL` to be configured. ```bash ./manage.py makefrontend ``` -------------------------------- ### Frontend API - StateBuilder Class Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Documentation for the StateBuilder class, responsible for reconstructing nested state from flat server instances. ```APIDOC ## Frontend API - StateBuilder Class ### Description Reconstructs nested state from flat server instances. Maintains an instance registry and rebuilds the nested structure by replacing foreign key IDs with object references. Reference changes propagate recursively to trigger React re-renders. ### Class Definition `StateBuilder()` ### `update(instances)` Processes a batch of instance updates from the server. * **Arguments:** * **instances** – Array of flat instances with `_instance_type`. ### `state` The current rebuilt nested state. Returns a new reference on each access to trigger React re-renders. ``` -------------------------------- ### Configure Django ASGI_APPLICATION Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Sets the ASGI_APPLICATION variable in Django settings to point to your project's ASGI application. This is necessary for Django Channels and RxDjango to function. ```python ASGI_APPLICATION = 'your_project.asgi.application' ``` -------------------------------- ### RxDjango Single Instance Channel with Permissions (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Extends the ContextChannel to handle single instances. It includes the `has_permission` static method for user authorization and an optional `get_instance_id` method to specify how to retrieve the instance ID from keyword arguments. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() @staticmethod def has_permission(user, **kwargs) def get_instance_id(self, **kwargs): # this is optional, by default returns the first kwarg return kwargs['my_model_id'] ``` -------------------------------- ### Configure WebSocket URL Patterns (Django ASGI) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Defines the WebSocket URL patterns for RxDjango channels within a Django project's `asgi.py`. It maps specific URL paths to the corresponding ContextChannel's ASGI application. ```python from myapp.channels import MyContextChannel websocket_urlpatterns = [ path('ws/myapp/instance//', MyContextChannel.as_asgi()), path('ws/myapp/list', MyContextListChannel.as_asgi()), ] application = ProtocolTypeRouter({ "http": app, "websocket": URLRouter( websocket_urlpatterns ), }) ``` -------------------------------- ### Implement RxDjango Consumer with ContextChannel Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md This snippet demonstrates how to implement consumer functionality in RxDjango by using the `@consumer` decorator on a `ContextChannel` subclass. It shows how to handle specific event types and join groups to receive events. ```python from rxdjango.channels import ContextChannel from rxdjango.consumers import consumer class MyChannel(ContextChannel): @consumer('some.event.type') def my_consumer(self, event): # handle event async def on_connect(tstamp): # Join a group to receive events await self.group_add('some-group') ``` -------------------------------- ### Broadcast Instance Update to Clients (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Manually broadcasts an instance update to all connected clients associated with a given anchor. Supports 'create', 'update', and 'delete' operations. This class method is part of the ContextChannel. ```python MyContextChannel.broadcast_instance(anchor_id, instance, operation='update') ``` -------------------------------- ### Define Backend Action for Frontend Call (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Illustrates how to define an action method on an RxDjango channel using the `@action` decorator. Type hints are crucial for automatic TypeScript interface generation. Changes to the channel's state are automatically broadcast. ```python from rxdjango.actions import action class MyContextListChannel(ContextChannel): ... @action async def change_instance_state(self, some_var: int) -> bool: # do something, changes in state will automatically be broadcast return result ``` -------------------------------- ### Broadcast Instance Update Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Manually broadcast an instance update to all connected clients. Requires anchor_id, instance, and optionally an operation type ('create', 'update', or 'delete'). ```python broadcast_instance(anchor_id, instance, operation='update') ``` -------------------------------- ### Define RxDjango ContextChannel with Serializer and Permissions Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Creates a custom ContextChannel by subclassing rxdjango.channels.ContextChannel. It defines a Meta class with a serializer and implements a has_permission method to control access to channel data. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() def has_permission(self, user, instance): # check if user has permission on instance return True ``` -------------------------------- ### Define RxDjango ContextChannel with State (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Demonstrates how to define a ContextChannel subclass in RxDjango. It requires a Meta class with a state property, typically a serializer. This is the core component for managing real-time state. ```python from rxdjango.channels import ContextChannel from myapp.serializers import MyNestedSerializer class MyContextChannel(ContextChannel): class Meta: state = MyNestedSerializer() ``` -------------------------------- ### Required Django Apps Configuration Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Specifies the essential Django applications required for RxDjango to function correctly. The order of `rxdjango` and `daphne` is crucial for proper integration with Django Channels. ```python INSTALLED_APPS = [ 'rxdjango', # Must come before daphne 'daphne', # Must come before staticfiles 'django.contrib.staticfiles', 'channels', ] ASGI_APPLICATION = 'your_project.asgi.application' ``` -------------------------------- ### Frontend API - PersistentWebSocket Class Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Documentation for the PersistentWebSocket class, a WebSocket wrapper with automatic reconnection and message routing. ```APIDOC ## Frontend API - PersistentWebSocket Class ### Description WebSocket wrapper with automatic reconnection and message routing. Features exponential backoff retry on connection drops, and routes incoming messages to type-specific handlers. ### `connect()` Initiates the WebSocket connection and sends the authentication token. ### `send(data)` Sends a string message through the WebSocket. * **Arguments:** * **data** – The message string to send. ### `disconnect(reason?)` Closes the connection. If `reason` is provided, it prevents reconnection. ``` -------------------------------- ### Configure RxDjango Frontend Directory and WebSocket URL Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Sets RX_FRONTEND_DIR to specify the directory for generated frontend Typescript files and RX_WEBSOCKET_URL for the application's websocket endpoint. This enables automatic generation of frontend communication interfaces. ```python RX_FRONTEND_DIR = os.path.join(BASE_DIR, '../frontend/src/app/modules') RX_WEBSOCKET_URL = "http://localhost:8000/ws" ``` -------------------------------- ### Call Backend Action from Frontend (TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md Shows how to invoke a backend action method defined in RxDjango from the frontend. When the method is called on the channel instance, it's executed asynchronously on the backend, and the results are returned. ```typescript const channel = new MyContextChannel(instanceId, auth.token); await channel.search(searchTerm); ``` -------------------------------- ### Access RxDjango Runtime State in React Frontend Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md This TypeScript code demonstrates how to access and use the RxDjango runtime state in a React frontend using the `useChannelState` hook. It shows how to import necessary types and provide them to the hook for proper type checking. ```typescript import { useChannelState } from "@rxdjango/react"; import { MyNestedType } from "my-rx-frontend-dir/myapp.interfaces"; import { MyContextChannel, MyContextChannelRuntimeState } from "my-rx-frontend-dir/myapp.channels"; const MyPage = () => { const channel = new MyContextChannel(instanceId, auth.token); const { state, runtimeState } = useChannelState(channel); } ``` -------------------------------- ### Connect React Component State to RxDjango Channel Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Demonstrates how to connect a React component's state to an RxDjango channel using the `useChannelState` hook. It shows initializing a channel with a model ID and authentication token, and how the state automatically updates with serialized data. ```typescript import { MyContextChannel } from 'app/modules/myapp.channels'; import { useChannelState } from '@rxdjango/react'; const channel = new MyContextChannel(mymodelId, token); const state = useChannelState(channel); ``` -------------------------------- ### ContextChannel Class (TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Base class for generated TypeScript channel classes. Manages WebSocket connection, authentication, state rebuilding, and RPC. It handles subscribing to state changes, specific instances, and calling backend actions. ```typescript class ContextChannel() { constructor(token: string); init(): void; disconnect(): void; subscribe(listener: (state: T) => void, noConnectionListener?: () => void): () => void; subscribeInstance(listener: (instance: any) => void, instance_id: number | string, instance_type: string): () => void; getInstance(instance_type: string, instance_id: number | string): any | null; callAction(action: string, params: any[]): Promise; } ``` -------------------------------- ### Define Runtime State for Frontend Synchronization Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/using-rxdjango.md This Python code defines a `RuntimeState` class using `TypedDict` within a `ContextChannel` subclass. This allows RxDjango to automatically relay the state to the frontend, persisting for each websocket connection. ```python from typing import TypedDict from rxdjango.channels import ContextChannel class MyChannel(ContextChannel): class RuntimeState(TypedDict): some_number_var: int some_bool_var: bool ``` -------------------------------- ### WebSocket Protocol - Incoming Messages Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Describes the message formats for messages sent from the client (React frontend) to the server (Django backend). ```APIDOC ## WebSocket Protocol - Incoming Messages ### Description Messages sent from the client to the server. ### Authentication This message must be the first message sent after establishing a connection. ```json { "token": "", "last_update": } ``` ### Action Call (RPC) Used to invoke methods on the server. ```json { "callId": , "action": "methodName", "params": [...] } ``` ``` -------------------------------- ### Generate Frontend Files with Django Management Command Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Executes the `makefrontend` Django management command to generate Typescript interfaces and frontend classes based on your serializers and channels. This command automates the creation of frontend code needed for communication. ```bash python manage.py makefrontend ``` -------------------------------- ### Register RxDjango Channel in ASGI Routing Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Defines a websocket URL pattern in the Django ASGI routing file (asgi/routing.py) to map a specific URL to the custom RxDjango ContextChannel. This makes the channel accessible via WebSocket. ```python from myapp.channels import MyContextChannel websocket_urlpatterns = [ path('ws/myapp//', MyContextChannel.as_asgi()), ] ``` -------------------------------- ### useChannelState Hook (React TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md React hook for subscribing to channel state. It provides the current state, connection status, and any errors encountered. Requires a ContextChannel instance as input. ```typescript function useChannelState(channel: ContextChannel | undefined): { state: any; connected: boolean; no_connection_since: number | null; runtimeState: any; empty: boolean; error: any; } ``` -------------------------------- ### Configure MongoDB URL for RxDjango Cache Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Configures the MONGO_URL and MONGO_STATE_DB settings for RxDjango's native cache system, which utilizes MongoDB. This enables efficient caching of state data. ```python MONGO_URL = 'mongodb://localhost:27017/' MONGO_STATE_DB = 'hot_state' ``` -------------------------------- ### Configure User Key for Real-time Updates (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Defines the field name that identifies the owning user for serializer instances. When set, instances are only sent to the WebSocket client whose user matches this field. This is configured within the `Meta` class of a DRF serializer. ```python class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = ['id', 'title', 'owner'] user_key = 'owner' ``` -------------------------------- ### PersistentWebSocket Class (TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md WebSocket wrapper with automatic reconnection and message routing. Features exponential backoff retry on connection drops and routes incoming messages to type-specific handlers. Provides methods to connect, send messages, and disconnect. ```typescript class PersistentWebSocket() { connect(): void; send(data: string): void; disconnect(reason?: string): void; } ``` -------------------------------- ### Configure Redis URL for RxDjango Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/README.md Sets the REDIS_URL in Django settings to configure the connection to the Redis server, which RxDjango uses for messaging. Ensure Redis is running on the specified host and port. ```python REDIS_URL = f'redis://127.0.0.1:6379/0' ``` -------------------------------- ### Broadcast System Message Command Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Broadcasts a message to all connected WebSocket clients through the system channel. This command is useful for sending system-wide notifications, such as maintenance alerts. ```bash python manage.py broadcast_system_message ``` -------------------------------- ### Broadcast Notification to Clients (Python) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/context-channel.md Sends a notification message to connected clients for a specific anchor. Optionally, notifications can be targeted to a single user if `user_id` is provided. This is a class method of ContextChannel. ```python MyContextChannel.broadcast_notification(anchor_id, {'message': 'Hello'}, user_id=None) ``` -------------------------------- ### useChannelInstance Hook (React TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md React hook for subscribing to a specific instance within the channel state. It returns the instance data or null if not available. Requires the channel, instance type, and instance ID. ```typescript function useChannelInstance(channel: ContextChannel | undefined, instance_type: string, instance_id: string | number | undefined): any | null; ``` -------------------------------- ### Delta Computation for Model Updates Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/caching.md Illustrates RxDjango's delta computation mechanism for efficiently broadcasting model changes. It serializes new states and computes minimal differences (deltas) for changed instances, sending new or deleted instances in full. It utilizes a C extension for performance with a Python fallback. ```python # Delta computation uses a C extension (`delta_utils_c`) for performance when # available, with a pure-Python fallback (`delta_utils`). # The C extension is automatically compiled during `pip install -e .`. ``` -------------------------------- ### StateBuilder Class (TypeScript) Source: https://github.com/cdiglobaltrack/rxdjango/blob/main/docs/api-reference.md Reconstructs nested state from flat server instances. It maintains an instance registry and rebuilds the nested structure by replacing foreign key IDs with object references, triggering React re-renders on changes. ```typescript class StateBuilder() { update(instances: any[]): void; get state(): T; } ```