摘要:接下来你就可以在项目的任何地方发送通知了像这样其中的参数释义发送通知的对象接收通知的对象动词短语链接到动作的对象可选执行通知的对象可选有点绕,举个栗子杜赛在搭建个人博客中对你发表了评论。有疑问请在杜赛的个人网站留言,我会尽快回复。
凭借你勤奋的写作,拜读你文章的用户越来越多,他们的评论也分散在众多的文章之中。作为博主,读者的留言肯定是要都看的;而读者给你留言,自然也希望得到回复。
怎么将未读的留言呈现给正确的用户呢?总不能用户自己去茫茫文章中寻找吧,那也太蠢了。给评论增加通知功能就是很流行的解决方案:比如微信朋友圈留言的通知、新浪微博留言的通知、以及各种社交平台的“小红点”。
本篇将以django-notifications为基础,非常高效的搭建一个简易的通知系统。
发送通知前面的步骤我们已经很熟悉了。
首先安装django-notifications:
(env) > pip install django-notifications-hq
注册app:
my_blog/settings.py ... INSTALLED_APPS = [ ... "notifications", ... ] ...
在根路由中安装路径:
my_blog/urls.py ... import notifications.urls urlpatterns = [ ... path("inbox/notifications/", include(notifications.urls, namespace="notifications")), ... ] ...
注意这里的notifications.urls没有像之前一样用字符串,是为了确保模块安装到正确的命名空间中。
数据迁移:
(env) > python manage.py migrate
app就安装好了。
接下来你就可以在项目的任何地方发送通知了!像这样:
from notifications.signals import notify notify.send(actor, recipient, verb, target, action_object)
其中的参数释义:
actor:发送通知的对象
recipient:接收通知的对象
verb:动词短语
target:链接到动作的对象(可选)
action_object:执行通知的对象(可选)
有点绕,举个栗子:杜赛 (actor) 在 Django搭建个人博客 (target) 中对 [你]() (recipient) [发表了]() (verb) [评论]() (action_object)。
因为我们想要在用户发表评论的时候发送通知,因此修改一下发表评论的视图:
comments/views.py ... from notifications.signals import notify from django.contrib.auth.models import User ... def post_comment(...): ... # 已有代码,创建新回复 if comment_form.is_valid(): ... # 已有代码,二级回复 if parent_comment_id: ... # 新增代码,给其他用户发送通知 if not parent_comment.user.is_superuser: notify.send( request.user, recipient=parent_comment.user, verb="回复了你", target=article, action_object=new_comment, ) return HttpResponse("200 OK") new_comment.save() # 新增代码,给管理员发送通知 if not request.user.is_superuser: notify.send( request.user, recipient=User.objects.filter(is_superuser=1), verb="回复了你", target=article, action_object=new_comment, ) return redirect(article) ...
2019/6/4 修正此代码。旧代码错误的将发送给管理员的notify放在了new_comment.save()的前面,导致action_object存储为NULL。
增加了两条notify的语句,分别位于两个if语句中:
第一个notify:用户之间可以互相评论,因此需要发送通知。if语句是为了防止管理员收到重复的通知。
第二个notify:所有的评论都会给管理员(也就是博主)发送通知,除了管理员自己。
其他的代码没有变化,注意位置不要错就行了。你可以试着发送几条评论,然后打开SQLiteStudio,查看notifications_notification表中的数据变化。
有效代码实际上只有4行,我们就完成了创建、发送通知的功能!相信你已经逐渐体会到运用第三方库带来的便利了。这就是站在了“巨人们”的肩膀上。小红点
后台创建通知的逻辑已经写好了,但是如果不能在前端显示出来,那也没起到作用。
而前端显示消息通知比较流行的是“小红点”,流行得都已经泛滥了,尽管很多软件其实根本就不需要。另一种形式是消息徽章,即一个红色方框中带有消息条目的计数。这两种方式都会用到博客页面中。
在位置的选择上,header是很合适的,因为它在博客的所有位置都会显示,很符合通知本身的定位。
因此修改header.html:
templates/header.html {% load notifications_tags %} {% notifications_unread as unread_count %} ...
django-notifications自带简易的模板标签,可以在前台模板中调用重要的通知相关的对象,在顶部引入就可以使用了。比如unread_count是当前用户的未读通知的计数。
Bootstrap自带有徽章的样式,但是却没有小红点的样式(至少我没有找到),所以就只能用svg自己画了,好在也不难。
svg是绘制矢量图形的标签,这里就不展开讲了,感兴趣请自行搜索相关文章。
随便评论几条,刷新页面看一看:
效果不错。但是链接的href是空的,接下来就处理。
未读与已读既然是通知,那么肯定能够分成”未读的“和”已读的“两种。在适当的时候,未读通知又需要转换为已读的。现在我们来开发功能集中处理它。
通知是一个独立的功能,以后有可能在任何地方用到,放到评论app中似乎并不合适。
所以新建一个app:
(env) > python manage.py startapp notice
注册:
my_blog/settings.py ... INSTALLED_APPS = [ ... "notice", ] ...
根路由:
my_blog/urls.py ... urlpatterns = [ ... # notice path("notice/", include("notice.urls", namespace="notice")), ] ...
接下来就是视图了。之前所有的视图都是用的视图函数,这次我们更进一步,用类视图来完成。忘记什么是类视图的,回忆一下前面类的视图章节。
编写视图:
notice/views.py from django.shortcuts import render, redirect from django.views import View from django.views.generic import ListView from django.contrib.auth.mixins import LoginRequiredMixin from article.models import ArticlePost class CommentNoticeListView(LoginRequiredMixin, ListView): """通知列表""" # 上下文的名称 context_object_name = "notices" # 模板位置 template_name = "notice/list.html" # 登录重定向 login_url = "/userprofile/login/" # 未读通知的查询集 def get_queryset(self): return self.request.user.notifications.unread() class CommentNoticeUpdateView(View): """更新通知状态""" # 处理 get 请求 def get(self, request): # 获取未读消息 notice_id = request.GET.get("notice_id") # 更新单条通知 if notice_id: article = ArticlePost.objects.get(id=request.GET.get("article_id")) request.user.notifications.get(id=notice_id).mark_as_read() return redirect(article) # 更新全部通知 else: request.user.notifications.mark_all_as_read() return redirect("notice:list")
视图共两个。
CommentNoticeListView:继承自ListView,用于展示所有的未读通知。get_queryset方法返回了传递给模板的上下文对象,unread()方法是django-notifications提供的,用于获取所有未读通知的集合。另外视图还继承了“混入类”LoginRequiredMixin,要求调用此视图必须先登录。
CommentNoticeUpdateView:继承自View,获得了如get、post等基础的方法。mark_as_read()、mark_all_as_read都是模块提供的方法,用于将未读通知转换为已读。if语句用来判断转换单条还是所有未读通知。
重复:阅读有困难的同学,请重新阅读类的视图查阅。
接下来就是新建urls.py了,写入:
notice/urls.py from django.urls import path from . import views app_name = "notice" urlpatterns = [ # 通知列表 path("list/", views.CommentNoticeListView.as_view(), name="list"), # 更新通知状态 path("update/", views.CommentNoticeUpdateView.as_view(), name="update"), ]
path()的第二个参数只能接收函数,因此别忘了要调用类视图的as_view()方法。
集中处理通知需要一个多带带的页面。新建templates/notice/list.html模板文件:
templates/notice/list.html {% extends "base.html" %} {% load staticfiles %} {% block title %} 通知 {% endblock title %} {% block content %}{% endblock content %}{% for notice in notices %}
- {{ notice.actor }} 在 {{ notice.target }} {{ notice.verb }}。 {{ notice.timestamp|date:"Y/m/d H:i" }}
{% endfor %}
模板中主要提供了两个功能:
点击button按钮清空所有未读通知
点击单个通知,将其转换为已读通知,并前往此评论所在的文章
末尾标签中的伪类选择器,作用是将已经点击过的通知字体颜色转换为浅灰色,优化用户体验。
最后就是补上入口:
templates/header.html ... 通知... ...
这样就完成了。
打开服务器,用一个普通账号评论几条,再登录管理员账号并进入通知页面:
就能看到不错的效果了。实现的效果是仅展示未读通知,当然也可以在下边展示已读通知,方便用户追溯。
总结通知功能非常的重要,特别是在你的博客成长壮大了之后。你还可以把它用在别的地方,比如每新发表一篇文章,就给你所有的“粉丝”推送一条通知,提醒他们可以来拜读了。具体如何扩展运用,就靠你脑洞大开了。
课后作业:前面的代码中,如果用户自己评论自己,同样也会收到通知。这种通知并没有必要,请修正它。
遇到困难,在教程示例代码找答案吧。
有疑问请在杜赛的个人网站留言,我会尽快回复。
或Email私信我:dusaiphoto@foxmail.com
项目完整代码:Django_blog_tutorial
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/43828.html
摘要:在父页面中文章详情模板添加需要执行锚点拼接的函数新增函数,处理二级回复去除尾部符号刷新并定位到锚点函数中运用了的三元运算符,翻译成人话就是如果成立则返回,如果不成立就返回。 老读者注意:上一章消息通知有个bug,即发给管理员的notify必须移动到new_comment.save()的后面,否则会导致action_object存储为NULL,并且导致本章的html拼接锚点失效。原文已...
摘要:每一条日志记录也包含级别,代表对应消息的严重程度。即格式化器,主要功能是确定最终输出的形式和内容。最好是日志能够按自然天进行记录和分割。 上一章学习了自动化测试,很好,现在我们可以绞尽脑汁写出一份全面的测试,来保证代码永远健康了。 话虽如此,但是作为一个独立开发者很难写出真正全面的测试代码。这是因为用户在使用你的网站时可不会循规蹈矩,而是会以各种怪异的姿势浏览网页、上传数据。但这也不是...
摘要:本章讲如何帮助健忘症患者,重置用户密码。实际上不仅内置了密码重置,还包括登录登出密码修改等功能。总结本章学习了使用第三方库,高效完成了重置密码的功能。有疑问请在杜赛的个人网站留言,我会尽快回复。 随着技术的发展,验证用户身份的手段越来越多,指纹、面容、声纹应有尽有,但密码依然是最重要的手段。 互联网处处都有密码的身影,甚至变成了现代人的一种负担。像笔者这样的,动辄几十个账号密码,忘记其...
摘要:博客网站的用户信息并不复杂,因此扩展就足够了。可以在这个基础上,扩展为一个美观详细的用户信息页面。当然最好再给个人信息添加一个入口。没有对用户的登录状态进行检查。总结本章使用一对一链接的方式,扩展并更新了用户信息。 可能你已经发现了,Django自带的User模型非常实用,以至于我们没有写用户管理相关的任何模型。 但是自带的User毕竟可用的字段较少。比方说非常重要的电话号码、头像等都...
摘要:用实现一个更实用的博客系统,让写作更简单,更愉快。博客相关页面博客首页博文详情后台管理相关页面后台首页添加文章文章列表标签管理分类管理系统消息用户列表友链管理用户个人信息全局设置普通用户登录所看到的页面环境后台模板后记看到这儿是不是已经迫不 July 用Django实现一个更实用的博客系统,让写作更简单,更愉快。 Demo 博客相关页面 博客首页 showImg(https://se...
阅读 2599·2021-11-12 10:36
阅读 2235·2021-08-23 09:47
阅读 1655·2019-08-30 15:44
阅读 1385·2019-08-30 14:10
阅读 2227·2019-08-29 16:52
阅读 2317·2019-08-29 16:40
阅读 1549·2019-08-29 16:17
阅读 2385·2019-08-26 13:21