Open SaadBazaz opened 2 years ago
Interesting idea there, though I think this should be as an add-in to this package.
I must point that usually messages from this package should not be persistent, and get deleted as soon as they are not relevant. This design is replicating the Django Messages framework, where the messages are stored in the session, and get deleted on logout.
With this in mind, it reduces the weight of creating many messages in the DB, because they will eventually get cleared when they will be read.
DBStorage
and MessagesViewSet
As you've said, create a new model that will store relation between a message and multiple users, each with info whether they've read the message or not.
Create a new storage object that will include those messages in the filtering, providing a similar interface like they are regular messages. This new storage should implement a way to send bulk messages to a list of users.
The user submitting the broadcast message, will create a new "master message" with relation for him. Any other recipient of that message will have a row in the bulk message model. The "master message" should not get deleted until all related bulk messages are read.
Create a new API view set to create and check status of bulk messages.
A new model that will obtain the relation between the user and the message:
class BulkMessage(models.Model):
message = models.ForeignKey(Message, on_delete=models.CASCADE)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
read_at = models.DateTimeField(blank=True, null=True, default=None, help_text="When the message was read.")
class Meta:
constraints = [
models.UniqueConstraint(fields=("message", "user"), name="unique_bulk_message"),
]
It will contain a manager like on the classic Message
that will have a filter for messages for a user and mark as read.
Some improvements for the DBStorage
to replace any place the do mark_read
with a storage method that will mark any unread messages as read (aka. self.get_unread_queryset().mark_read()
). This will later be overriden.
Implement a new BulkDBStorage
object that will inherit DBStorage
and override functions:
get_queryset
-> To include message relevant to the request by the relation with the user through BulkMessage
get_unread_queryset
- > To include unread message from the relation through BulkMessage
mark_all_read
-> Mark read any messages that are directly attached to the request.user
, and also any BulkMessage
for that user.There a new method can be implemented like:
def add_bulk(self, recipients: Sequence[User], level: int, message: str, extra_tags=''):
message = Message.objects.create_message(self.request, message, level, extra_tags=extra_tags)
BulkMessage.objects.bulk_create([
BulkMessage(message=message, user=user)
for user in recipients
])
Implement a viewset, with the methods:
create
-> Send a new bulk messagelist
-> List all bulk messages with count aggregation for recipients and read messagesget
-> Get specific bulk message with the list of recipients (users)Three possible locations to add this feature:
drf_message.bulk_messages
)drf-messages
(such as drf-messages-bulk
)drf-messages
Please provide you thoughts on my design
Problem To send a single message, e.g. an update alert message to users, or even a greeting for the holiday, I have to add a message for each user separately. This could clog up the database, specially since all the messages are the same, just the user is different.
Possible solution A separate table with User -> Message mapping, an admin form/action for Bulk messages, etc.
Describe alternatives you've considered Alternatives can be Firebase Messaging, but I would prefer a DRF-only solution.