本文分享自華為雲社群《構建實時訊息通知系統: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 構建一個功能強大的訊息通知系統,其中涵蓋了以下主要內容:
- 透過定義模型、建立訊號、編寫訊號處理器,實現了通知系統的基本框架。
- 整合了前端框架 Bootstrap,並使用 Ajax 技術實現了標記通知為已讀的功能,以及實時更新未讀通知數量的功能,提升了使用者體驗。
- 新增了通知刪除功能,使使用者可以更靈活地管理通知。
- 引入了非同步任務處理技術 Celery,將通知的生成和傳送操作轉換為非同步任務,提高了系統的效能和響應速度。
透過這些步驟,我們建立了一個功能完善的訊息通知系統,使用者可以及時瞭解到與其相關的重要資訊,並且可以自由地管理和處理通知,從而增強了應用的互動性、可用性和效能。
點選關注,第一時間瞭解華為雲新鮮技術~