Search code examples
databasedjangonotificationsforum

Django forum database design


I'm extending an existing Django forum app (DjangoBB) to allow users to opt in/out of notifications for specific forums and/or specific threads. I already have an existing notification infrastructure on my site, and an existing global setting to turn forum notifications on/off.

What I want to do is allow each user to subscribe/unsubscribe from specific forums or threads, effectively overriding their global setting. For example, if my global setting is 'Notifications Off', then I would not get any notifications, unless I set a specific forum to 'Notifications On', in which case I'll get notifications for everything in that forum, unless I set a thread in that forum to 'Notifications Off'. If any thread or topic doesn't have a setting set, it defaults up the chain.

My question is what's the best way to represent all of this in my database in Django? I have two ideas:

class ForumNotificationSetting(models.Model):
    user = models.ForeignKey(User)
    forum = models.ForeignKey(Forum)
    setting = models.NullBooleanField(default=None)

I would also have a similar model for TopicNotificationSetting. This way, whenever a user changes their forum settings, I create (or modify) a NotificationSetting object to reflect their new settings. This method seems simple, but the downside is if lots of people create settings for lots of forums, then creating notifications for everyone would be O(n^2) whenever a new forum post is made. (I think...?)

The second way I can think of would be to create a ManyToMany field in each user's profile for all forums to which they have set settings for. This way seems more complicated (since I'd have to have 4 total M2M fields for 'forums on', 'forums off', 'topics on', and 'topics off'), and I'm not sure if there would be any performance benefits or not.

How would you solve this problem?


Solution

  • Perhaps you could create an M2M relationship on the level of the Thread or Forum object, e.g.:

    class Thread(models.Model):
        subscribers = models.ManyToManyField(User)
        other attributes...
    

    Then, as a user (un)subscribes from a Thread, you add or delete them from the Thread object's subscribers property.

    In your application logic, when a user creates a post, thread or forum, you could just check their overall notification setting and - if set to True - add them to to the subscribers property of the newly created Thread, Post or Forum.

    Each time a thread, post or forum is updated, you could then notify all subscribers.

    I'd assume you'd need some logic to handle escalation (I can't find the proper word, sorry), i.e. I'd assume a notification for a Thread update should also trigger a notification for a Forum update (or should it?). And then you should of course take care that a user doesn't get spammed with post, thread and forum notifications for a single Post update...