前言
本文章记录在网站搭建过程中使用django_notifications的方法,使用的是前后端不分离的方法,完全作为记录以方便日后浏览使用,故仅供浏览者参考使用。
以下是本篇文章正文内容
目录
一、准备工作
1.安装django-notifications
:
(env) > pip install django-notifications-hq
2.在项目settings文件中注册app
objects_web/settings.py
...
INSTALLED_APPS = [
...
'notifications',
...
]
3.在根路由中写入路径
objects_web/urls.py
...
import notifications.urls
urlpatterns = [
...
# 通知
path('inbox/notifications/', include(notifications.urls, namespace='notifications')),
...
]
...
4.数据迁移
(env) > python manage.py migrate
二、基本使用
1. 生成通知
你可以在任意的地方导入并发送消息
from notifications.signals import notify
notify.send(actor, recipient, verb, action_object,
target, level, description, public,timestamp, **kwargs)
上面是完整的语法,参数分别为:
- actor(发件人):任何类型的对象。(必需)如果打算使用关键字参数,要使用sender
- recipient(收件人): 一组或一个用户查询集或列表的用户(必需的)。
- verb(动作): 一个字符串(必需的)。
- action_object:任何类型的对象(可选的)。
- target(目标):任何类型的对象(可选的)。
- level(等级):Notification.LEVELS ('success', 'info', 'warning', 'error') 之一(可选的)。
- description(描述): 一个字符串(可选的)。
- public(公共的):一个布尔值(默认值=True)(可选的)。
- timestamp(时间戳)
其中,发件人(actor),收件人(recipient),动作(verb)这三项是在使用时必须传入的,其他项可根据实际情况使用。
我在项目根部录下创建了一个notifications.py文件,用来放通知功能相关的代码
然后把发送通知的方法封装成了一个函数,直接上代码:
objects_web/notification.py
from notifications.signals import notify
def send_notifications(actor, verb, recipient, target=None,
description=None, **kwargs):
"""
这里原本放的是上文各个参数的说明
"""
notify.send(sender=actor,
recipient=recipient,
verb=verb,
target=target,
description=description,
**kwargs
)
然后在任意app下的views.py文件的任意位置中调用:
userProfile/views.py
from userProfile.notifications import send_notifications
send_notifications(request.user, "转正申请", request.user,
description="sp",level="danger")
这样就生成了一条简单的通知啦!
2. 前端显示数量
首先,必须先实时看到我有多少条未读的通知:
templates/notifications_unread.html
<!-- 引入notifications的模板标签 -->
{% load notifications_tags %}
{% notifications_unread as unread_count %}
<div class="wrapper">
<!-- Navbar -->
<nav class="main-header navbar navbar-expand-md navbar-light navbar-white">
<div class="container">
<!-- Right navbar links -->
<ul class="order-1 order-md-3 navbar-nav navbar-no-expand ml-auto">
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#">
<i class="far fa-bell"></i>
{% if unread_count %}
<span class="badge badge-warning navbar-badge">
{{ unread_count }}</span>{% endif %}
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<span class="dropdown-item dropdown-header">{% if unread_count %}{{ unread_count }}条通知{% else %}
暂无通知{% endif %}</span>
<div class="dropdown-divider"></div>
{% if unread_count %}
<a href="{% url "userProfile:user_notifications" %}" class="dropdown-item">
<i class="fa fa-comment"></i> {{ unread_count }} 条未读通知
</a>
{% endif %}
<div class="dropdown-divider"></div>
<a href="{% url "userProfile:user_notifications" %}" class="dropdown-item dropdown-footer">查看所有<i
class="fas fa-arrow-circle-right"></i></a>
</div>
</li>
</ul>
</div>
</nav>
django-notifications
自带简易的模板标签,可以在前台模板中调用重要的通知相关的对象,在顶部引入就可以使用了。unread_count
是当前用户的未读通知的计数。
请大家忽略我的html代码,其实比较重要的就是这一句:
<!-- 如果有通知,显示通知的数量;样式可以随便设置 -->
{% if unread_count %}
{{ unread_count }}
{% endif %}
然后随便发几条通知,看下效果
这样未读通知的数量就可以显示啦。
3. 前端显示未读通知
django-notifications提供了获取用户未读信息的方法,我同样把他封装成一个函数方法
传入用户的对象,返回用户未读通知列表
objects_web/notification.py
def get_unread_list(user):
"""
return:返回用户未读列表
"""
return user.notifications.unread()
在view.py文件中,获取用户未读信息传到前端
userProfile/views.py
def user_notifications(request):
unread_list = get_unread_list(request.user)
return render(request, "indexuser/userinfo/notifications_unread.html", {"unread_list": unread_list})
在前端遍历这个列表
同样的,请忽略前端代码,主要看用法
templates/notifications_unread.html
{% for notice in unread_list %}
{% if notice.description == "sp" %}
<tr>
<td class="mailbox-star">
<i class="fas fa-star text-{{ notice.level }}"></i>
</td>
<td class="mailbox-name">
<a><b class="text-primary">{{ notice.verb }}</b></a>
</td>
<td class="mailbox-subject">
您收到了来自<bclass="text-success">{{ notice.actor }}</b>的{{ notice.verb }}
</td>
<td class="mailbox-date">
<b>{{ notice.timestamp }}</b>
</td>
<td class="mailbox-attachment">
<a href="{% url 'userProfile:approval_details' %}?id=
{{notice.target.object_id }}&type={{ notice.target.type }}" title="查看">
<span class="text-primary"><i class="fas fa-paperclip"></i></span>
</a>
</td>
<td class="mailbox-attachment">
<a href="{% url "userProfile:user_change_unread" %}?notice_id={{ notice.id
}}" title="已读"><span class="text-success"><i class="fa fa-check"></i>
</span></a>
</td>
</tr>
{% endif %}
{% endfor %}
看下效果
OK,前端已经可以查看未读的通知了。
4. 未读变已读
django-notifications同样提供了转变的方法,继续写函数
userProfile/views.py
# 未读变更为已读
def change_unread(request):
notice_id = request.GET.get('notice_id')
if notice_id:
# 更新一条
request.user.notifications.get(id=notice_id).mark_as_read()
return redirect("userProfile:user_notifications")
else:
# 更新全部
request.user.notifications.mark_all_as_read()
return redirect("userProfile:user_notifications")
为了实现单条已读和全部已读,我把它分成了两种情况的请求
一种是前端带着该条通知的id请求,一种是不带,则全部更新。
上前段代码,单条的已读就在上文的内容中,可以试着找一下,我这里把它重新摘出来。
templates/notifications_unread.html
<!-- 单条带id的请求 -->
<td class="mailbox-attachment">
<a href="{% url "userProfile:user_change_unread" %}?notice_id={{ notice.id }}"
title="已读"><span class="text-success"><i class="fa fa-check"></i></span></a>
/td>
<!-- 全部不带id的请求 -->
<button type="button" class="btn btn-tool">
<a href="{% url "userProfile:user_change_unread" %}"
class="text-success font-weight-bold">
<i class="fa fa-check"></i>全部已读
</a>
</button>
这样,通过点击单条通知后的对勾,或者点击右上角的全部已读,就实现了未读转已读的功能了~
同时,其实到这里,通知的基本功能已经实现了,但是如果想要查看已读的信息该怎么办呢,目前这样显然是不行的,接着往下。
三、灵活使用
1. 软删除
如果只按上面的用法,已读信息其实是已经被直接删除的,我们就无法再查看已读的信息。
如果想要保留已读的通知,需要在settings.py文件下做一项配置,实现“软删除”
在settings.py写入:
objects_web/settings.py
...
DJANGO_NOTIFICATIONS_CONFIG = { 'USE_JSONFIELD': True}
...
当写入这条配置之后,unread和read的方法将包含一个过滤器:deleted=False。
read方法其实就是获取已读信息的方式。
接下来,我们找到已读的信息,将它们传到前端
2. 前端显示已读通知
userProfile/views.py
def notifications_read(request):
read_list = get_read_list(request.user)
return render(request, "indexuser/userinfo/notifications_read.html", {"read_list": read_list})
前端的遍历方法同上一样,代码就不再重复,直接看效果
这样已读的通知就出来了
同样,已读的信息也可以彻底进行删除,继续写函数方法,同样分为单条删除和一起删除
使用QuerySet.mark_all_as_deleted()方法
userProfile/views.py
# 已读变更为删除
def user_delete_read(request):
notice_id = request.GET.get('notice_id')
if notice_id:
request.user.notifications.filter(id=notice_id).mark_all_as_deleted()
return redirect("userProfile:notifications_read")
# 删除全部已读通知
else:
request.user.notifications.read().mark_all_as_deleted()
return redirect("userProfile:notifications_read")
需要注意的是,因为mark_all_as_deleted()是NotificationQuerySet的方法,所以不能用get方法来获取单条通知,必须用filter,哪怕它只有一条。
OK,到这里,基本的已读、未读、未读转已读、已读删除就全部搞定了,还有很多实用的方法,有特殊需求的可以去django-notifications的官方网站查看一下,那里还提供了各种方法
django-notifications官网
https://pypi.org/project/django-notifications-hq/
总结
目前这些内容已经足够当前项目的使用,官网还提供了实时更新通知的JavaScript方法,以后有需要的时候可以用一下,本文仍然只作为个人平时的记录和后期的查看用,这里记录两个大佬的博客地址,全是干货,涵盖的内容很多,也可做平时学习用:
杜赛的博客https://www.dusaiphoto.com/topic/刘江的博客
https://www.liujiangblog.com/blog/