本文分享自华为云社区《构建实时消息告诉体系: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 %}{% 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,将告诉的生成和发送操作转换为异步使命,提高了体系的性能和响应速度。

经过这些步骤,咱们建立了一个功用完善的消息告诉体系,用户能够及时了解到与其相关的重要信息,并且能够自由地办理和处理告诉,从而增强了运用的交互性、可用性和性能。

点击关注,第一时间了解华为云新鲜技能~