You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular 4中结合Django后端使用django-notifications处理通知?

Integrating django-notifications with Angular 4

Got it, let's break down how to make these two tools play nicely together. The core issue here is that Angular 4 runs as a separate frontend layer with its own template system—it can't natively parse the raw HTML/JS snippets from the django-notifications package. Instead, we need to build a custom bridge between your Django backend (which stores and manages notifications) and your Angular frontend (which renders and interacts with them). Here's a step-by-step approach:

1. Expose Notification Data via a Django API

First, you need to make your django-notifications data accessible to Angular through a REST API. The easiest way to do this is with Django REST Framework (DRF):

  • Create a serializer for the Notification model to convert database objects to JSON:

    from rest_framework import serializers
    from notifications.models import Notification
    
    class NotificationSerializer(serializers.ModelSerializer):
        # Use StringRelatedField to get human-readable names instead of IDs
        actor = serializers.StringRelatedField()
        target = serializers.StringRelatedField()
        action_object = serializers.StringRelatedField()
    
        class Meta:
            model = Notification
            fields = ['id', 'actor', 'verb', 'target', 'action_object', 'timestamp', 'unread']
    
  • Build API views to fetch unread notifications and mark them as read:

    from rest_framework import generics
    from rest_framework.permissions import IsAuthenticated
    from notifications.models import Notification
    from .serializers import NotificationSerializer
    
    class UserUnreadNotifications(generics.ListAPIView):
        serializer_class = NotificationSerializer
        permission_classes = [IsAuthenticated]
    
        def get_queryset(self):
            # Return only unread notifications for the logged-in user
            return Notification.objects.unread().filter(recipient=self.request.user)
    
    class MarkNotificationAsRead(generics.UpdateAPIView):
        serializer_class = NotificationSerializer
        permission_classes = [IsAuthenticated]
        queryset = Notification.objects.all()
    
        def perform_update(self, serializer):
            # Use the built-in method from django-notifications to mark as read
            serializer.instance.mark_as_read()
    
  • Map these views to URLs in your Django project's urls.py so Angular can reach them.

2. Create an Angular Notification Service

Next, build an Angular service to handle all communication with your Django API. This will encapsulate fetching notifications, marking them as read, etc.:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class NotificationService {
  // Adjust this to match your Django API's base URL
  private apiBaseUrl = '/api/notifications/';

  constructor(private http: HttpClient) {}

  // Fetch all unread notifications for the current user
  getUnreadNotifications(): Observable<any[]> {
    return this.http.get<any[]>(`${this.apiBaseUrl}unread/`);
  }

  // Mark a specific notification as read
  markAsRead(notificationId: number): Observable<any> {
    return this.http.patch(`${this.apiBaseUrl}${notificationId}/mark-read/`, {});
  }

  // Optional: Fetch all notifications (read + unread)
  getAllNotifications(): Observable<any[]> {
    return this.http.get<any[]>(`${this.apiBaseUrl}all/`);
  }
}

Don't forget to add HttpClientModule to your Angular app's main module to enable HTTP requests!

3. Build the Angular Notification Component

Now create a component to display notifications and handle user interactions. Here's a basic, functional example:

Component TypeScript

import { Component, OnInit } from '@angular/core';
import { NotificationService } from './notification.service';

@Component({
  selector: 'app-notifications',
  templateUrl: './notifications.component.html',
  styleUrls: ['./notifications.component.css']
})
export class NotificationsComponent implements OnInit {
  unreadNotifications: any[] = [];

  constructor(private notificationService: NotificationService) {}

  ngOnInit(): void {
    this.loadUnreadNotifications();
  }

  loadUnreadNotifications(): void {
    this.notificationService.getUnreadNotifications().subscribe(
      (notifications) => {
        this.unreadNotifications = notifications;
      },
      (error) => {
        console.error('Failed to load notifications:', error);
      }
    );
  }

  markNotificationAsRead(notificationId: number): void {
    this.notificationService.markAsRead(notificationId).subscribe(
      () => {
        // Update the local list to remove the now-read notification
        this.unreadNotifications = this.unreadNotifications.filter(n => n.id !== notificationId);
      },
      (error) => {
        console.error('Failed to mark notification as read:', error);
      }
    );
  }
}

Component Template

<div class="notifications-container">
  <button class="notification-toggle">
    Notifications 
    <span *ngIf="unreadNotifications.length > 0" class="unread-badge">{{ unreadNotifications.length }}</span>
  </button>
  
  <div class="notification-dropdown" *ngIf="unreadNotifications.length > 0">
    <div *ngFor="let notification of unreadNotifications" class="notification-item">
      <p>
        <strong>{{ notification.actor }}</strong> 
        {{ notification.verb }} 
        {{ notification.target || notification.action_object }}
      </p>
      <small class="timestamp">{{ notification.timestamp | date:'short' }}</small>
      <button (click)="markNotificationAsRead(notification.id)" class="mark-read-btn">Mark as Read</button>
    </div>
  </div>
  
  <p *ngIf="unreadNotifications.length === 0" class="no-notifications">No unread notifications</p>
</div>

Component CSS (Optional)

.notifications-container {
  position: relative;
  display: inline-block;
}

.notification-toggle {
  padding: 8px 16px;
  cursor: pointer;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.unread-badge {
  background-color: #dc3545;
  color: white;
  border-radius: 50%;
  padding: 2px 6px;
  font-size: 12px;
  margin-left: 4px;
}

.notification-dropdown {
  position: absolute;
  top: 100%;
  right: 0;
  background: white;
  border: 1px solid #ddd;
  border-radius: 4px;
  min-width: 280px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  margin-top: 4px;
}

.notification-item {
  padding: 12px;
  border-bottom: 1px solid #eee;
}

.notification-item:last-child {
  border-bottom: none;
}

.timestamp {
  display: block;
  color: #666;
  font-size: 12px;
  margin: 4px 0;
}

.mark-read-btn {
  font-size: 12px;
  padding: 4px 8px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.no-notifications {
  padding: 12px;
  color: #666;
  font-size: 14px;
}

4. Handle Authentication & CSRF

Since your Django API requires authenticated users, make sure Angular sends the necessary credentials:

  • For session-based auth, add withCredentials: true to your HttpClient requests (or configure it globally via an interceptor).
  • For CSRF protection, create an Angular interceptor to automatically read the CSRF cookie set by Django and include it in the X-CSRFToken header of your requests.

5. Optional: Real-Time Notifications

If you want notifications to appear in real-time without page reloads, integrate Django Channels with WebSockets. Use Angular's native WebSocket API or the rxjs/webSocket module to connect to your Django WebSocket endpoint and listen for new notifications as they're created.


内容的提问来源于stack exchange,提问作者Shoaib Iqbal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:45:27