一文教你實戰構建消息通知系統Django

本文分享自華爲雲社區《構建實時消息通知系統:Django實戰指南》,作者:檸檬味擁抱。

在Web應用程序中,實現消息通知系統是至關重要的,它可以幫助用戶及時瞭解到與其相關的事件或動態。Django提供了信號機制,可以用於實現這樣的通知系統。本文將介紹如何使用Django的信號機制來構建一個簡單但功能強大的消息通知系統,並提供相應的代碼和實例。

1. 安裝 Django

首先,確保你已經安裝了 Django。你可以通過 pip 安裝它:

pip install django

2. 創建 Django 項目和應用

創建一個 Django 項目,並在其中創建一個應用:

django-admin startproject notification_system
cd notification_system
python manage.py startapp notifications

3. 定義模型

在 notifications/models.py 文件中定義一個模型來存儲通知信息:

from django.db import models
from django.contrib.auth.models import User

class Notification(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    message = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    read = models.BooleanField(default=False)

4. 創建信號

在 notifications/signals.py 文件中創建信號,該信號將在需要發送通知時觸發:

from django.dispatch import Signal

notification_sent = Signal(providing_args=["user", "message"])

5. 編寫信號處理器

在 notifications/handlers.py 文件中編寫信號處理器,處理信號並創建相應的通知:

from django.dispatch import receiver
from .signals import notification_sent
from .models import Notification

@receiver(notification_sent)
def create_notification(sender, **kwargs):
    user = kwargs['user']
    message = kwargs['message']
    Notification.objects.create(user=user, message=message)

6. 發送通知

在你的應用程序中的適當位置,發送信號以觸發通知:

from django.contrib.auth.models import User
from notifications.signals import notification_sent

# 例如,發送通知給特定用戶
user = User.objects.get(username='username')
notification_sent.send(sender=None, user=user, message='你有一個新消息')

7. 顯示通知

在你的應用程序中,可以通過查詢通知模型來顯示用戶的通知:

from notifications.models import Notification

# 例如,在視圖中查詢並顯示通知
def notifications_view(request):
    user_notifications = Notification.objects.filter(user=request.user)
    return render(request, 'notifications.html', {'notifications': user_notifications})

8. 標記通知爲已讀

當用戶查看通知時,你可能需要將它們標記爲已讀。你可以在視圖中執行此操作:

def mark_as_read(request, notification_id):
    notification = Notification.objects.get(pk=notification_id)
    notification.read = True
    notification.save()
    return redirect('notifications_view')

9. 定義通知模板

創建一個 HTML 模板來呈現通知信息。在 templates/notifications.html 文件中定義:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Notifications</title>
</head>
<body>
    <h1>Notifications</h1>
    <ul>
        {% for notification in notifications %}
        <li{% if notification.read %} style="color: grey;"{% endif %}>
            {{ notification.message }}
            {% if not notification.read %}
            <a href="{% url 'mark_as_read' notification.id %}">Mark as Read</a>
            {% endif %}
        </li>
        {% endfor %}
    </ul>
</body>
</html>

10. 配置 URL

配置 URL 來處理通知相關的請求。在 notification_system/urls.py 文件中:

from django.urls import path
from notifications.views import notifications_view, mark_as_read

urlpatterns = [
    path('notifications/', notifications_view, name='notifications_view'),
    path('notifications/mark_as_read/<int:notification_id>/', mark_as_read, name='mark_as_read'),
]

11. 運行服務器

運行 Django 服務器以查看效果:

python manage.py runserver

現在,你可以訪問 http://127.0.0.1:8000/notifications/ 查看通知頁面,並且點擊“標記爲已讀”鏈接來標記通知。

12. 集成前端框架

爲了提升通知頁面的用戶體驗,我們可以使用一些流行的前端框架來美化頁面並添加一些交互功能。這裏以Bootstrap爲例。

首先,安裝Bootstrap:

pip install django-bootstrap4

在 settings.py 中配置:

INSTALLED_APPS = [
    ...
    'bootstrap4',
    ...
]

修改通知模板 notifications.html,引入Bootstrap的樣式和JavaScript文件,並使用Bootstrap的組件來美化頁面:

{% load bootstrap4 %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Notifications</title>
    {% bootstrap_css %}
</head>
<body>
    <div class="container">
        <h1 class="mt-5">Notifications</h1>
        <ul class="list-group mt-3">
            {% for notification in notifications %}
            <li class="list-group-item{% if notification.read %} list-group-item-light{% endif %}">
                {{ notification.message }}
                {% if not notification.read %}
                <a href="{% url 'mark_as_read' notification.id %}" class="btn btn-sm btn-primary ml-2">Mark as Read</a>
                {% endif %}
            </li>
            {% endfor %}
        </ul>
    </div>
    {% bootstrap_javascript %}
</body>
</html>

13. 使用 Ajax 實現標記爲已讀功能

我們可以使用 Ajax 技術來實現標記通知爲已讀的功能,這樣可以避免刷新整個頁面。修改模板文件和視圖函數如下:

在模板中,使用 jQuery 來發送 Ajax 請求:

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
    $(document).ready(function() {
        $('.mark-as-read').click(function(e) {
            e.preventDefault();
            var url = $(this).attr('href');
            $.ajax({
                type: 'GET',
                url: url,
                success: function(data) {
                    if (data.success) {
                        window.location.reload();
                    }
                }
            });
        });
    });
</script>

修改視圖函數 mark_as_read

from django.http import JsonResponse

def mark_as_read(request, notification_id):
    notification = Notification.objects.get(pk=notification_id)
    notification.read = True
    notification.save()
    return JsonResponse({'success': True})

14. 添加通知計數功能

爲了讓用戶可以清晰地知道有多少未讀通知,我們可以添加一個通知計數的功能,將未讀通知的數量顯示在頁面上。

首先,在 notifications/views.py 中修改 notifications_view 視圖函數:

def notifications_view(request):
    user_notifications = Notification.objects.filter(user=request.user)
    unread_count = user_notifications.filter(read=False).count()
    return render(request, 'notifications.html', {'notifications': user_notifications, 'unread_count': unread_count})

然後,在通知模板中顯示未讀通知的數量:

<div class="container">
    <h1 class="mt-5">Notifications</h1>
    <div class="alert alert-info mt-3" role="alert">
        You have {{ unread_count }} unread notification(s).
    </div>
    <ul class="list-group mt-3">
        {% for notification in notifications %}
        <li class="list-group-item{% if notification.read %} list-group-item-light{% endif %}">
            {{ notification.message }}
            {% if not notification.read %}
            <a href="{% url 'mark_as_read' notification.id %}" class="btn btn-sm btn-primary ml-2 mark-as-read">Mark as Read</a>
            {% endif %}
        </li>
        {% endfor %}
    </ul>
</div>

15. 實時更新通知計數

爲了使通知計數實時更新,我們可以使用 Ajax 技術定期請求服務器以獲取最新的未讀通知數量。

在通知模板中添加 JavaScript 代碼:

<script>
    function updateUnreadCount() {
        $.ajax({
            type: 'GET',
            url: '{% url "unread_count" %}',
            success: function(data) {
                $('#unread-count').text(data.unread_count);
            }
        });
    }
    $(document).ready(function() {
        setInterval(updateUnreadCount, 5000); // 每5秒更新一次
    });
</script>

在 notifications/urls.py 中添加一個新的 URL 路由來處理未讀通知數量的請求:

from django.urls import path
from .views import notifications_view, mark_as_read, unread_count

urlpatterns = [
    path('notifications/', notifications_view, name='notifications_view'),
    path('notifications/mark_as_read/<int:notification_id>/', mark_as_read, name='mark_as_read'),
    path('notifications/unread_count/', unread_count, name='unread_count'),
]

最後,在 notifications/views.py 中定義 unread_count 視圖函數:

from django.http import JsonResponse

def unread_count(request):
    user_notifications = Notification.objects.filter(user=request.user, read=False)
    unread_count = user_notifications.count()
    return JsonResponse({'unread_count': unread_count})

16. 添加通知刪除功能

除了標記通知爲已讀之外,有時用戶還可能希望能夠刪除一些通知,特別是一些不再需要的通知。因此,我們可以添加一個刪除通知的功能。

首先,在模板中爲每個通知添加一個刪除按鈕:

<ul class="list-group mt-3">
    {% for notification in notifications %}
    <li class="list-group-item{% if notification.read %} list-group-item-light{% endif %}">
        {{ notification.message }}
        <div class="btn-group float-right" role="group" aria-label="Actions">
            {% if not notification.read %}
            <a href="{% url 'mark_as_read' notification.id %}" class="btn btn-sm btn-primary mark-as-read">Mark as Read</a>
            {% endif %}
            <a href="{% url 'delete_notification' notification.id %}" class="btn btn-sm btn-danger delete-notification">Delete</a>
        </div>
    </li>
    {% endfor %}
</ul>

然後,在 notifications/urls.py 中添加一個新的 URL 路由來處理刪除通知的請求:

urlpatterns = [
    ...
    path('notifications/delete/<int:notification_id>/', delete_notification, name='delete_notification'),
]

接着,在 notifications/views.py 中定義 delete_notification 視圖函數:

def delete_notification(request, notification_id):
    notification = Notification.objects.get(pk=notification_id)
    notification.delete()
    return redirect('notifications_view')

最後,爲了使用戶可以通過 Ajax 刪除通知,我們可以修改模板中的 JavaScript 代碼:

<script>
    $(document).ready(function() {
        $('.delete-notification').click(function(e) {
            e.preventDefault();
            var url = $(this).attr('href');
            $.ajax({
                type: 'GET',
                url: url,
                success: function(data) {
                    if (data.success) {
                        window.location.reload();
                    }
                }
            });
        });
    });
</script>

17. 添加異步任務處理

在實際應用中,通知系統可能需要處理大量的通知,而生成和發送通知可能是一個耗時的操作。爲了避免阻塞用戶請求,我們可以使用異步任務處理來處理通知的生成和發送。

17.1 安裝 Celery

首先,安裝 Celery 和 Redis 作爲消息代理:

pip install celery redis

17.2 配置 Celery

在 Django 項目的根目錄下創建一個名爲 celery.py 的文件,並添加以下內容:

import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'notification_system.settings')

app = Celery('notification_system')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

在 settings.py 中添加 Celery 配置:

CELERY_BROKER_URL = 'redis://localhost:6379/0'

17.3 創建異步任務

在 notifications/tasks.py 中定義異步任務來處理通知的生成和發送:

from celery import shared_task
from .models import Notification

@shared_task
def send_notification(user_id, message):
    user = User.objects.get(pk=user_id)
    Notification.objects.create(user=user, message=message)

17.4 觸發異步任務

在你的應用程序中,當需要發送通知時,使用 Celery 的 delay() 方法觸發異步任務:

from notifications.tasks import send_notification

send_notification.delay(user_id, '你有一個新消息')

總結:

本文介紹瞭如何使用 Django 構建一個功能強大的消息通知系統,其中涵蓋了以下主要內容:

  1. 通過定義模型、創建信號、編寫信號處理器,實現了通知系統的基本框架。
  2. 集成了前端框架 Bootstrap,並使用 Ajax 技術實現了標記通知爲已讀的功能,以及實時更新未讀通知數量的功能,提升了用戶體驗。
  3. 添加了通知刪除功能,使用戶可以更靈活地管理通知。
  4. 引入了異步任務處理技術 Celery,將通知的生成和發送操作轉換爲異步任務,提高了系統的性能和響應速度。

通過這些步驟,我們建立了一個功能完善的消息通知系統,用戶可以及時瞭解到與其相關的重要信息,並且可以自由地管理和處理通知,從而增強了應用的交互性、可用性和性能。

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章