ModelStream

A common reason to stream data is to send page updates when a model is created, modified, or deleted. To organize these events in one place, Turbo Django uses ModelStream. These classes will trigger the code to run when a model instance is saved and deleted. ModelStream objects are declared and automatically detected in streams.py.

When a ModelStream is registered to a model, the model instance will automatically gain a .stream attribute that references the stream. For this reason, only one model stream can be attached to each model.

Primary Key Needed

You can only broadcast to instances that have a primary key. A ValueError is thrown when trying to broadcast to an object that does not have a primary key set.

Example

The following demonstrates a sample implementation of ModelStreams for a chat application. In this examples, a user would subscribe to a Room, however, the messages are the items being added and removed. A stream is created for both models - giving them both .stream attributes. When the message is saved, the message then references it’s parent room stream, and either appends or replaces the chat message if it was created or modified. If the message is deleted, the parent room stream is notified to remove the message block with the provided id.

app/streams.py
from .models import Message, Room

import turbo

class RoomStream(turbo.ModelStream):

    class Meta:
        model = Room



class MessageStream(turbo.ModelStream):

    class Meta:
        model = Message

    def on_save(self, message, created, *args, **kwargs):
        if created:
            message.room.stream.append("chat/message.html", {"message": message}, id="messages")
        else:
            message.room.stream.replace("chat/message.html", {"message": message}, id=f"message-{message.id}")

    def on_delete(self, message, *args, **kwargs):
        message.room.stream.remove(id=f"message-{message.id}")

    def user_passes_test(self, user):
        # if user.can_access_message(self.pk):
        #    return True
        return True