Skip to content

Notifications

Overview

The Notifications app provides a comprehensive in-app notification system for Jend-Z, enabling real-time user engagement through various notification types. The system automatically generates notifications for user interactions such as likes, comments, replies, mentions, and messages, helping users stay connected with platform activity.

Data Model

Notification Model

The Notification model represents all in-app notifications sent to users.

Core Fields

  • id (UUID): Unique identifier
  • user (ForeignKey): Notification recipient (CustomUser)
  • actor (ForeignKey): User who triggered the notification (CustomUser, optional)
  • message (TextField): Notification message content
  • is_read (BooleanField): Read status (default: false)
  • created_at (DateTimeField): Notification creation timestamp

Notification Types

  • notification_type (CharField): Type of notification

Available Types:

mention - "Mention" - User mentioned in post/comment
post_like - "Post Like" - Post received a like
post_reply - "Post Reply" - Comment added to post
comment_reply - "Comment Reply" - Reply to user's comment
new_post - "New Post in Community" - New post in followed community
new_message - "New Message" - Direct message received
general - "General" - General platform notifications

Target Reference

  • target_id (UUIDField): ID of related object (post, comment, message, etc.)
  • target_type (CharField): Type of related object ("Post", "Comment", "conversation", etc.)

This flexible reference system allows notifications to link to any platform content without tight coupling.

API Endpoints

Notification Management

1. List User Notifications

Endpoint: GET /api/notifications/

Authentication: Bearer token required

Description: Retrieve all notifications for the current user, ordered by most recent first.

Response:

{
  "count": 25,
  "next": "http://api.example.com/api/notifications/?page=2",
  "previous": null,
  "results": [
    {
      "id": "notification-uuid",
      "user": "user-uuid",
      "actor": {
        "id": "actor-uuid",
        "username": "johndoe",
        "display_name": "John Doe",
        "profile_picture": "https://example.com/media/profile_pictures/john.jpg"
      },
      "actor_username": "johndoe",
      "notification_type": "post_like",
      "target_id": "post-uuid",
      "target_type": "Post",
      "message": "johndoe liked your post",
      "is_read": false,
      "created_at": "2024-01-15T14:30:00Z"
    },
    {
      "id": "notification-uuid-2",
      "user": "user-uuid",
      "actor": {
        "id": "actor-uuid-2",
        "username": "janedoe",
        "display_name": "Jane Doe",
        "profile_picture": "https://example.com/media/profile_pictures/jane.jpg"
      },
      "actor_username": "janedoe",
      "notification_type": "comment_reply",
      "target_id": "comment-uuid",
      "target_type": "Comment",
      "message": "janedoe replied to your comment.",
      "is_read": true,
      "created_at": "2024-01-15T12:15:00Z"
    },
    {
      "id": "notification-uuid-3",
      "user": "user-uuid",
      "actor": {
        "id": "actor-uuid-3",
        "username": "adminuser",
        "display_name": "Admin User",
        "profile_picture": "https://example.com/media/profile_pictures/admin.jpg"
      },
      "actor_username": "adminuser",
      "notification_type": "general",
      "target_id": null,
      "target_type": null,
      "message": "Welcome to Jend-Z! Complete your profile to get started.",
      "is_read": false,
      "created_at": "2024-01-15T10:00:00Z"
    }
  ]
}

2. Mark Notification as Read

Endpoint: PATCH /api/notifications/{notification_id}/

Authentication: Bearer token required

Description: Update notification read status. Only the notification recipient can modify their notifications.

Request Body:

{
  "is_read": true
}

Success Response:

{
  "id": "notification-uuid",
  "user": "user-uuid",
  "actor": {
    "id": "actor-uuid",
    "username": "johndoe",
    "display_name": "John Doe",
    "profile_picture": "https://example.com/media/profile_pictures/john.jpg"
  },
  "actor_username": "johndoe",
  "notification_type": "post_like",
  "target_id": "post-uuid",
  "target_type": "Post",
  "message": "johndoe liked your post",
  "is_read": true,
  "created_at": "2024-01-15T14:30:00Z"
}

Permission Error:

{
  "detail": "Not found."
}

Automatic Notification Generation

The notification system automatically creates notifications based on user interactions through Django signals.

Comment Reply Notifications

Trigger: When a user replies to another user's comment

Generated For: Original comment author

Conditions:

  • Reply author must be different from original comment author
  • Notification type: comment_reply
  • Target: The reply comment

Example Message: "username replied to your comment."

Message Notifications

Trigger: When a user sends a direct message

Generated For: All conversation participants except sender

Smart Notification Logic:

  • First Message: Always generates notification
  • Subsequent Messages: Only notifies if 5+ minutes have passed since last message
  • Prevents Spam: Avoids notification flooding during active conversations

Conditions:

  • Notification type: new_message
  • Target: The conversation ID
  • Target type: "conversation"

Example Message: "You have a new message from username"

Post Interaction Notifications

Based on the posts app code, additional notifications are generated for:

Post Likes

Trigger: When a user likes a post Generated For: Post author Notification Type: post_like Target: The liked post

Post Comments

Trigger: When a user comments on a post Generated For: Post author Notification Type: post_reply Target: The post

Notification Categories

Social Interactions

  • Mentions: User tagged in content (@username)
  • Likes: Content received appreciation
  • Replies: Responses to user's content
  • Comments: New discussion on user's posts

Communication

  • Messages: Direct messages from other users
  • Conversation Updates: Important conversation events

Community Activity

  • New Posts: Content in followed communities
  • Community Events: Community-related updates

System Notifications

  • General: Platform announcements, welcome messages, feature updates
  • Administrative: Account-related notifications

Notification Targeting

Target Reference System

The notification system uses a flexible targeting approach:

Target ID + Target Type

  • Flexibility: Can reference any platform object
  • Extensibility: Easy to add new target types
  • Loose Coupling: No foreign key constraints to specific models

Common Target Types

Post - References posts for likes, comments
Comment - References comments for replies
conversation - References message conversations
Community - References community-related notifications
User - References user-related notifications

Example Usage

# Post like notification
Notification.objects.create(
    user=post.user,
    actor=liker,
    notification_type='post_like',
    target_id=post.id,
    target_type='Post',
    message=f"{liker.username} liked your post"
)

# Comment reply notification
Notification.objects.create(
    user=parent_comment.user,
    actor=replier,
    notification_type='comment_reply',
    target_id=reply.id,
    target_type='Comment',
    message=f"{replier.username} replied to your comment"
)

Message Notification Intelligence

Conversation Notification Logic

The system implements smart notification timing for messages to balance engagement with user experience:

First Message

  • Always Notifies: Ensures users know about new conversations
  • Immediate: No delay for conversation starters

Follow-up Messages

  • 5-Minute Cooldown: Prevents notification spam during active chats
  • Activity Detection: Checks time since last message in conversation
  • User-Friendly: Allows natural conversation flow without interruption

Implementation Details

# Check conversation history
last_messages = Message.objects.filter(
    conversation=conversation
).exclude(id=instance.id).order_by('-created_at')

should_notify = False

if not last_messages.exists():  # First message
    should_notify = True
else:
    last_message = last_messages.first()
    if (timezone.now() - last_message.created_at) > timedelta(minutes=5):
        should_notify = True

User Experience Features

Actor Information

Each notification includes detailed actor information:

Actor Object

  • User ID: For linking to actor's profile
  • Username: For display and mention purposes
  • Display Name: User-friendly name
  • Profile Picture: Visual identification

Benefits

  • Rich UI: Display actor's profile information
  • Quick Actions: Navigate to actor's profile
  • Visual Recognition: Show profile pictures in notifications
  • Consistent Data: Always includes actor details when available

Read Status Tracking

Unread Notifications

  • Default State: All notifications start as unread
  • Visual Indicators: Frontend can highlight unread notifications
  • Count Tracking: Easy to count unread notifications

Mark as Read

  • Individual Control: Users can mark specific notifications as read
  • Persistent State: Read status maintained across sessions
  • Bulk Operations: Frontend can implement "mark all as read"

Pagination Support

The notification list endpoint includes automatic pagination:

Default Behavior

  • Ordered Results: Most recent notifications first
  • Page-based: Standard pagination with next/previous links
  • Count Information: Total notification count provided

Performance Optimization

  • User Filtering: Only loads current user's notifications
  • Efficient Queries: Optimized database queries with proper indexing
  • Lazy Loading: Only loads displayed page of results

Error Handling

Common Error Responses

Unauthorized Access:

{
  "detail": "Authentication credentials were not provided."
}

Notification Not Found:

{
  "detail": "Not found."
}

Permission Denied:

{
  "detail": "Not found."
}

Note: Permission errors return "Not found" instead of "Permission denied" to avoid information disclosure about notification existence.

HTTP Status Codes

  • 200 OK: Successful retrieval or update
  • 401 Unauthorized: Authentication required
  • 404 Not Found: Notification not found or access denied
  • 500 Internal Server Error: Server error

Integration Patterns

Frontend Integration

Real-time Updates

// Check for new notifications
const checkNotifications = async () => {
  const response = await api.get("/api/notifications/");
  const unreadCount = response.data.results.filter((n) => !n.is_read).length;
  updateNotificationBadge(unreadCount);
};

// Mark notification as read
const markAsRead = async (notificationId) => {
  await api.patch(`/api/notifications/${notificationId}/`, {
    is_read: true,
  });
  refreshNotifications();
};

Notification Display

// Display notification with actor info
const NotificationItem = ({ notification }) => (
  <div className={`notification ${!notification.is_read ? "unread" : ""}`}>
    <img src={notification.actor.profile_picture} alt="" />
    <div>
      <p>{notification.message}</p>
      <span>{notification.created_at}</span>
    </div>
  </div>
);

Backend Integration

Creating Custom Notifications

from notifications.models import Notification

# Custom notification creation
def notify_user(user, actor, notification_type, message, target_id=None, target_type=None):
    Notification.objects.create(
        user=user,
        actor=actor,
        notification_type=notification_type,
        message=message,
        target_id=target_id,
        target_type=target_type
    )

# Usage example
notify_user(
    user=post_author,
    actor=request.user,
    notification_type='post_like',
    message=f"{request.user.username} liked your post",
    target_id=post.id,
    target_type='Post'
)

Signal-based Notifications

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=SomeModel)
def create_notification(sender, instance, created, **kwargs):
    if created:
        Notification.objects.create(
            user=instance.recipient,
            actor=instance.sender,
            notification_type='custom_type',
            message=f"New {sender.__name__} created",
            target_id=instance.id,
            target_type=sender.__name__
        )