Django学习笔记之自定义中间件的使用(实现简单站内消息)

1、django流程、中间件流程图

2、中间件的作用

官方文档所说:Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.(中间件是连接到Django请求/响应处理的框架。它是一个轻量级的、低层次的“插件”系统,用于全局改变Django的输入或输出。)

也就是说,当你想在执行视图前后,对输入输出进行添加或删除某些值,就可以用到中间件。

常见的应用场景就是要对每个请求都获取请求的用户名,或者是想要实现站内消息,如下效果:

首先,设计思路:在数据库中新建一张表用来记录通知的内容、通知的接受者(外键,关联用户表)、通知发出的时间、通知的状态(状态默认为0,表示未读;用户点击阅读后,修改状态为1,表示已读)

因为通知一栏每个页面都会有,而且阅读通知后通知状态就会变成已读,显示的通知个数就变为0,由此可见未读通知个数是随时可变的,所以对于每次请求都需要去数据库中查询,此用户的未读通知个数为多少,再传递给模板显示出来。

由于每个请求都要对输入添加用户名和未读通知个数再传递给视图,所以这用中间件就很简单了。

3、中间件的使用

  • 在APP下新建一个py文件,如下middleware.py:

  • 在中间件middleware.py文件中写需要的逻辑函数(从session中获取用户名,然后查询用户表获取此用户ID,再通过用户ID查询通知表该用户通知状态为未读的对象个数,并将查询到的个数写入request中):
from django.utils.deprecation import MiddlewareMixin
from web import models
from rbvc.models import UserInfo


class count_notice_num(MiddlewareMixin):
            def process_request(self,request):
                try:
                    self.username = request.session['username']
                except:
                    return None

                self.user_id = UserInfo.objects.get(username=self.username).id

                self.notice_num = models.Notice.objects.filter(userinfo_id=self.user_id).filter(has_read= 0).count()

                if self.notice_num == 0:
                    self.notice_num = ''

                request.notice_num = self.notice_num
                return None

    由于我们是要在执行视图前添加数据,所以我们需要改写 process_request函数

  • 再于settings.py文件中声明这个中间件的路径:rbvc.middleware.count_notice_num(app名称.文件名.类名或函数名)
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'rbvc.middleware.RBACMiddleware',
    'rbvc.middleware.count_notice_num',
]
  • 接着,改写视图返回模板函数render(新建py文件,名字路径随意,方便复用)
from django.shortcuts import render

def mp_render(request, template, context={}):
    try:
        context['username'] =request.session['username']
        context['notice_num']=request.notice_num
    except:
        pass
    return render(request,template, context)
  • 最后,把视图中原来使用render的地方全部改写成自定义的mp_render(注意使用前,根据上述新建的py文件名字路径导入 mp_render函数)

   所有原来用   return render(request, '***.html',locals())  的,改写成  return mp_render(request, '***.html',locals()) 其余的逻辑不变,即可以完成在原来项目基础上,在每个请求后执行视图前添加用户名、用户未读消息个数,再传递给模板。

            <a class="user-menu right"  href="/notice/list">
                通知
                <i class="fa fa-envelope-o" aria-hidden="true"></i>
                <span class="badge bg-danger">{{ notice_num }}</span>
            </a>

现在模板就能识别 notice_num这个变量了。

发布了24 篇原创文章 · 获赞 30 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/yufen9987/article/details/90287268