django-eventstream

repository·master·Indexed 21 days ago

https://github.com/fanout/django-eventstream

A library providing Django views for pushing real-time data to clients using the Server-Sent Events (SSE) protocol. Version 5.3.4 supports integration with Daphne, Redis for scaling, and GRIP proxies like Pushpin. It includes built-in support for Django REST Framework via the [drf] extra, event storage for reliable delivery, and custom channel authorization through a ChannelManager.

Tokens
13K
Snippets
49
Records
62
Agent score
74%

What's inside django-eventstream

  1. Run the Chat example with Fanout Cloud

    master

    To use Fanout Cloud for real-time streaming in this example, configure the GRIP_URL in your .env file using your realm credentials.

    1. Set GRIP_URL in .env: GRIP_URL=https://api.fanout.io/realm/{realm-id}?iss={realm-id}&key=base64:{realm-key}
    2. Use ngrok to create a local tunnel: ngrok http 8000
    3. Run the specialized management command to link the tunnel to Fanout Cloud: python manage.py runserver_ngrok

    Requests to your Fanout Cloud domain (e.g., https://{realm-id}.fanoutcdn.com/) will be routed through the ngrok tunnel to your local server.

    # In .env
    GRIP_URL=https://api.fanout.io/realm/{realm-id}?iss={realm-id}&key=base64:{realm-key}
    
    # In a separate shell
    ngrok http 8000
    
    # Run the server
    python manage.py runserver_ngrok
  2. Setup the Chat example application

    master

    To run the chat example, create a virtual environment, install the required dependencies, initialize the database, and create an empty .env file.

    Note: In this specific example, the django_eventstream library is loaded via a relative path from within the repository rather than being installed via pip.

    virtualenv --python=python3 venv
    . venv/bin/activate
    pip install -r requirements.txt
    touch .env
    python manage.py migrate
    
    # To run the server:
    python manage.py runserver
  3. Scale Django EventStream with Redis

    master

    To allow send_event to work from separate processes (like management commands) or multiple application instances, configure Redis.

    1. Install Redis:
    pip install redis
    1. Configure settings.py: Set the EVENTSTREAM_REDIS dictionary with your Redis connection details.
    EVENTSTREAM_REDIS = {
        'host': 'redis',
        'port': 6379,
        'db': 0,
    }
  4. Setup the Chat REST Framework example

    master

    To set up the chat application using the Django REST Framework version of django-eventstream, follow these steps to prepare your environment, install dependencies from local source, and migrate the database:

    1. Create and activate a virtual environment.
    2. Install dependencies from requirements.txt.
    3. Crucial: Install the Django REST Framework version of django-eventstream from the local source directory using pip install "../../[drf]".
    4. Create an empty .env file.
    5. Run database migrations.
    virtualenv --python=python3 venv
    . venv/bin/activate
    pip install -r requirements.txt
    touch .env
    # Install the DRF version of the library from local source
    pip install "../../[drf]"
    python manage.py migrate
  5. Implement custom channel authorization

    master

    To control which users can access specific channels, implement a custom ChannelManager by subclassing DefaultChannelManager and overriding can_read_channel.

    1. Define the manager:
    from django_eventstream.channelmanager import DefaultChannelManager
    
    class MyChannelManager(DefaultChannelManager):
        def can_read_channel(self, user, channel):
            if channel.startswith('_') and user is None:
                return False
            return True
    1. Register in settings.py:
    EVENTSTREAM_CHANNELMANAGER_CLASS = 'myapp.channelmanager.MyChannelManager'
    1. Trigger permission updates: When permissions change, call channel_permission_changed(user, channel_name) to force clients to disconnect if they no longer have access.
    from django_eventstream import channel_permission_changed
    
    channel_permission_changed(user, '_mychannel')
  6. Run the Chat example with Pushpin

    master

    To use Pushpin locally, set the GRIP_URL to your local Pushpin instance and route traffic to your Django server.

    1. Set GRIP_URL=http://localhost:5561 in your .env.
    2. Start Pushpin with a route to your local server: pushpin --route="* localhost:8000"
    3. Start your Django server: python manage.py runserver
    4. Access the application at http://localhost:7999/.
    # In .env
    GRIP_URL=http://localhost:5561
    
    # Start Pushpin
    pushpin --route="* localhost:8000"
    
    # Start server
    python manage.py runserver
  7. Install and set up Django EventStream

    master

    To install Django EventStream, install the package along with daphne. For Django REST Framework support, use the [drf] extra.

    1. Install dependencies:
    pip install django-eventstream daphne

    Or with DRF support:

    pip install django-eventstream[drf] daphne
    1. Configure settings.py: Add daphne and django_eventstream to INSTALLED_APPS and define your ASGI_APPLICATION.

    2. Configure urls.py: Include django_eventstream.urls in your URL patterns and specify the allowed channels via keyword arguments.

    from django.urls import path, include
    import django_eventstream
    
    urlpatterns = [
        path("events/", include(django_eventstream.urls), {"channels": ["test"]}),
    ]
    INSTALLED_APPS = [
        ...,
        "daphne",
        "django_eventstream",
    ]
    
    ASGI_APPLICATION = "your_project.asgi.application"
  8. Setup the Time example project

    master

    To run the Time example, which demonstrates sending the current time over a stream, follow these steps to prepare the environment, install dependencies, and initialize the database:

    1. Create and activate a virtual environment.
    2. Install the required dependencies using pip install -r requirements.txt.
    3. Create an empty .env file for environment configuration.
    4. Run Django migrations to set up the database.

    Note: In this specific example, the django_eventstream library is loaded via a relative path from within the repository rather than being installed as a standard package via pip.

    virtualenv --python=python3 venv
    . venv/bin/activate
    pip install -r requirements.txt
    touch .env
    python manage.py migrate
  9. Run the Chat REST API and Client servers

    master

    The chat application requires two servers to run: the Django REST API server and a simple HTTP server for the web client.

    1. Start the REST API server: Run the Django management command.
    2. Start the Client server: Navigate to the chat-client directory and start a local HTTP server.
    3. Access the app: Open your browser to http://localhost:9000/.
    # Start the REST API server
    python manage.py runserver 0.0.0.0:8000
    
    # In a new terminal, start the chat-client server
    cd chat-client
    python -m http.server 9000
  10. Enable reliable event delivery with Event Storage

    master

    By default, events are not persisted. To ensure clients can recover missed messages after a disconnection, enable event storage.

    1. Run migrations:
    python manage.py migrate
    1. Configure storage class in settings.py: Set EVENTSTREAM_STORAGE_CLASS to django_eventstream.storage.DjangoModelStorage. This persists events for 24 hours.
    EVENTSTREAM_STORAGE_CLASS = 'django_eventstream.storage.DjangoModelStorage'
  11. Use Django EventStream with Django REST Framework

    master

    To integrate with DRF, register viewsets on your router and configure the appropriate renderers in settings.py.

    Registration Options:

    • By function: Use configure_events_view_set to specify channels and message types.
    • By class: Use EventsViewSet directly.

    Required Renderers: django_eventstream.renderers.SSEEventRenderer is required for SSE. For the Browsable API, add django_eventstream.renderers.BrowsableAPIEventStreamRenderer.

    Important: Place eventstream renderers after JSONRenderer and BrowsableAPIRenderer in your DEFAULT_RENDERER_CLASSES list.

    from django.urls import path, include
    from django_eventstream.viewsets import EventsViewSet, configure_events_view_set
    
    router.register(
        "events1",
        configure_events_view_set(channels=["channel1", "channel2"], messages_types=["message", "info"]),
        basename="events1"
    )
    
    router.register(
        "events2",
        EventsViewSet(channels=["channel1", "channel2"]),
        basename="events2"
    )
    
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',
            'django_eventstream.renderers.SSEEventRenderer',
            'django_eventstream.renderers.BrowsableAPIEventStreamRenderer'
        ]
    }