沈阳润才教育CRM
一、CRM初始
CRM,客户关系管理系统(Customer Relationship Management)。企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销售循环:新客户的招徕、保留旧客户、提供客户服务及进一步提升企业和客户的关系,并运用市场营销工具,提供创新式的个人化的客户商谈和服务,辅以相应的信息系统或信息技术如数据挖掘和数据库营销来协调所有公司与顾客间在销售、营销以及服务上的交互。
此系统主要是以教育行业为背景,为公司开发的一套客户关系管理系统。考虑到各位童鞋可能处于各行各业,为了扩大的系统使用范围,特此将该项目开发改为组件化开发,让同学们可以日后在自己公司快速搭建类似系统及新功能扩展。
- 权限系统,一个独立的rbac组件。
- stark组件,一个独立的curd组件。
- crm业务,以教育行业为背景并整合以上两个组件开发一套系统。
二、权限组件之权限控制
1. 问:为什么程序需要权限控制?
答:生活中的权限限制,① 看灾难片电影《2012》中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临;② 屌丝们,有没有想过为什么那些长得漂亮身材好的姑娘在你身边不存在呢?因为有钱人和漂亮姑娘都是珍贵稀有的,稀有的人在一起玩耍和解锁各种姿势。而你,无权拥有他们,只能自己玩自己了。
程序开发时的权限控制,对于不同用户使用系统时候就应该有不同的功能,如:
- 普通员工
- 部门主管
- 总监
- 总裁
所以,只要有不同角色的人员来使用系统,那么就肯定需要权限系统。
2. 问:为什么要开发权限组件?
答:假设你今年25岁,从今天开始写代码到80岁,每年写5个项目,那么你的一生就会写275个项目,保守估计其中应该有150+个都需要用到权限控制,为了以后不再重复的写代码,所以就开发一个权限组件以便之后55年的岁月中使用。 亲,不要太较真哦,你觉得程序员能到80岁么,哈哈哈哈哈哈哈
偷偷告诉你:老程序员开发速度快,其中一个原因是经验丰富,另外一个就是他自己保留了很多组件,新系统开发时,只需把组件拼凑起来基本就可以完成。
3. 问:web开发中权限指的是什么?
答:web程序是通过 url 的切换来查看不同的页面(功能),所以权限指的其实就是URL,对url控制就是对权限的控制。
结论:一个人有多少个权限就取决于他有多少个URL的访问权限。
权限表结构设计:第一版
问答环节中已得出权限就是URL的结论,那么就可以开始设计表结构了。
- 一个用户可以有多个权限。
- 一个权限可以分配给多个用户。
你设计的表结构大概会是这个样子:
现在,此时此刻是不是觉得自己设计出的表结构棒棒哒!!!
But,无论是是否承认,你还是too young too native,因为老汉腚眼一看就有问题....
问题:假设 “老男孩”和“Alex” 这俩货都是老板,老板的权限一定是非常多。那么试想,如果给这俩货分配权限时需要在【用户权限关系表中】添加好多条数据。假设再次需要对老板的权限进行修改时,又需要在【用户权限关系表】中找到这俩人所有的数据进行更新,太他妈烦了吧!!! 类似的,如果给其他相同角色的人来分配权限时,必然会非常繁琐。
权限表结构设计:第二版
聪明机智的一定在上述的表述中看出了写门道,如果对用户进行角色的划分,然后对角色进行权限的分配,这不就迎刃而解了么。
- 一个人可以有多个角色。
- 一个角色可以有多个人。
- 一个角色可以有多个权限。
- 一个权限可以分配给多个角色。
表结构设计:
这次调整之后,由原来的【基于用户的权限控制】转换成【基于角色的权限控制】,以后再进行分配权限时只需要给指定角色分配一次权限,给众多用户再次分配指定角色即可。
models.py 示例
from django.db import models class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name='标题', max_length=32)
url = models.CharField(verbose_name='含正则的URL', max_length=128)</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title
class Role(models.Model):
"""
角色
"""
title = models.CharField(verbose_name='角色名称', max_length=32)
permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title
class UserInfo(models.Model):
"""
用户表
"""
name = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
email = models.CharField(verbose_name='邮箱', max_length=32)
roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span> self.name</pre>
小伙子,告诉你一个事实,不经意间,你居然设计出了一个经典的权限访问控制系统:rbac(Role-Based Access Control)基于角色的权限访问控制。你这么优秀,为什么不来老男孩IT教育?路飞学城也行呀! 哈哈哈哈。
注意:现在的设计还不是最终版,但之后的设计都是在此版本基础上扩增的,为了让大家能够更好的理解,我们暂且再此基础上继续开发,直到遇到无法满足的情况,再进行整改。
源码示例:猛击下载
客户管理之权限控制
学习知识最好的方式就是试错,坑踩多了那么学到的知识自然而然就多了,所以接下里下来我们用《客户管理》系统为示例,提出功能并实现,并且随着功能越来越多,一点点来找出问题,并解决问题。
目录结构:
luffy_permission/
├── db.sqlite3
├── luffy_permission
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── rbac # 权限组件,便于以后应用到其他系统
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── templates
└── web # 客户管理业务
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
rbac/models.py
from django.db import models class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name='标题', max_length=32)
url = models.CharField(verbose_name='含正则的URL', max_length=128)</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title
class Role(models.Model):
"""
角色
"""
title = models.CharField(verbose_name='角色名称', max_length=32)
permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True)</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title
class UserInfo(models.Model):
"""
用户表
"""
name = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
email = models.CharField(verbose_name='邮箱', max_length=32)
roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Role', blank=True)</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.name
rbac/models.py
web/models.py
from django.db import models class Customer(models.Model):
"""
客户表
"""
name = models.CharField(verbose_name='姓名', max_length=32)
age = models.CharField(verbose_name='年龄', max_length=32)
email = models.EmailField(verbose_name='邮箱', max_length=32)
company = models.CharField(verbose_name='公司', max_length=32) class Payment(models.Model):
"""
付费记录
"""
customer = models.ForeignKey(verbose_name='关联客户', to='Customer')
money = models.IntegerField(verbose_name='付费金额')
create_time = models.DateTimeField(verbose_name='付费时间', auto_now_add=True) web/models.py
《客户管理》系统截图:基本增删改查和Excel导入源码下载:猛击这里
以上简易版客户管理系统中的URL有:
- 客户管理
- 客户列表:/customer/list/
- 添加客户:/customer/add/
- 删除客户:/customer/list/(?P<cid>\d+)/
- 修改客户:/customer/edit/(?P<cid>\d+)/
- 批量导入:/customer/import/
- 下载模板:/customer/tpl/
- 账单管理
- 账单列表:/payment/list/
- 添加账单:/payment/add/
- 删除账单:/payment/del/(?P<pid>\d+)/
- 修改账单:/payment/edit/<?P<pid>\d+/
那么接下来,我们就在权限组件中录入相关信息:
- 录入权限
- 创建用户
- 创建角色
- 用户分配角色
- 角色分配权限
这么一来,用户登录时,就可以根据自己的【用户】找到所有的角色,再根据角色找到所有的权限,再将权限信息放入session,以后每次访问时候需要先去session检查是否有权访问。
已录入权限数据源码下载:猛击这里
含用户登录权限源码下载:猛击这里(简易版)
含用户登录权限源码下载:猛击这里
至此,基本的权限控制已经完成,基本流程为:
- 用户登录,获取权限信息并放入session
- 用户访问,在中间件从session中获取用户权限信息,并进行权限验证。
所有示例中的账户信息:
账户一:
用户名:alex
密码:123 账户二:
用户名:wupeiqi
密码:123
本文参考链接:
https://www.cnblogs.com/wupeiqi/articles/9178982.html
作业
1. django程序
2. 两个app
- rbac,权限相关所有的东西
- models.py(三个类5张表)
- web,随便写业务处理
- models.py 3. 找URL并使用django admin 录入到权限表
urlpatterns = [
url(r'^customer/list/$', customer.customer_list),
url(r'^customer/add/$', customer.customer_add),
url(r'^customer/edit/(?P<cid>\d+)/$', customer.customer_edit),
url(r'^customer/del/(?P<cid>\d+)/$', customer.customer_del),
url(r'^customer/import/$', customer.customer_import),
url(r'^customer/tpl/$', customer.customer_tpl),url(r</span><span style="color: #800000;">'</span><span style="color: #800000;">^payment/list/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, payment.payment_list),
url(r</span><span style="color: #800000;">'</span><span style="color: #800000;">^payment/add/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, payment.payment_add),
url(r</span><span style="color: #800000;">'</span><span style="color: #800000;">^payment/edit/(?P<pid>\d+)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, payment.payment_edit),
url(r</span><span style="color: #800000;">'</span><span style="color: #800000;">^payment/del/(?P<pid>\d+)/$</span><span style="color: #800000;">'</span><span style="color: #000000;">, payment.payment_del),
]
4. 角色和用户管理
5. 写代码
a. 用户登陆
- 获取用户信息放入session
- 获取当前用户所有的权限并写入session
b. 编写中间件做权限信息校验
- 获取当前请求URL
- 获取当前用户的所有权限
- 权限校验
请下载github代码
https://github.com/987334176/luffy_permission/archive/v1.0.zip
录入数据
修改rbac目录下的admin.py,注册表
from django.contrib import admin # Register your models here.
from rbac import models admin.site.register(models.Permission)
admin.site.register(models.Role)
admin.site.register(models.UserInfo)
创建超级用户
python manage.py createsuperuser
登录admin后台,开始录入数据
先增加用户,再增加角色,最后设置权限
注意,权限来自于urls.py
添加url完成之后,绑定角色和权限
相关权限表关系
表记录(大概)
测试ORM
这个作业,主要是能得到用户的授权url列表。如果这都不能查询出来,那么作业可以放弃了!
先不着急写页面,用脚本测试orm
修改rbac目录下的tests.py
from django.test import TestCase # Create your tests here.
import os if name == "main":
# 设置django环境
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "luffy_permission.settings")
import django
django.setup()</span><span style="color: #0000ff;">from</span> rbac <span style="color: #0000ff;">import</span><span style="color: #000000;"> models </span><span style="color: #008000;">#</span><span style="color: #008000;"> 固定用户名和密码</span>
user = <span style="color: #800000;">'</span><span style="color: #800000;">xiao</span><span style="color: #800000;">'</span><span style="color: #000000;">
pwd </span>= <span style="color: #800000;">'</span><span style="color: #800000;">123</span><span style="color: #800000;">'</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 查询表,用户名和密码是否匹配</span>
obj = models.UserInfo.objects.filter(name=user, password=<span style="color: #000000;">pwd).first()
role </span>= obj.roles.all() <span style="color: #008000;">#</span><span style="color: #008000;"> 查询当前用户的所有角色</span>
permissions_list = [] <span style="color: #008000;">#</span><span style="color: #008000;"> 空列表,用来存放用户能访问的url列表</span> <span style="color: #0000ff;">for</span> i <span style="color: #0000ff;">in</span> role: <span style="color: #008000;">#</span><span style="color: #008000;"> 循环角色</span>
per = i.permissions.all() <span style="color: #008000;">#</span><span style="color: #008000;"> 查看当前用户所有角色的所有权限</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print(i.permissions.all())</span>
<span style="color: #0000ff;">for</span> j <span style="color: #0000ff;">in</span><span style="color: #000000;"> per:
</span><span style="color: #008000;">#</span><span style="color: #008000;"> print(j.url)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 将所有授权的url添加到列表中</span>
permissions_list.append(j.url)
</span><span style="color: #0000ff;">print</span>(permissions_list)</pre>
使用Pycharm执行输出:
['^customer/list/$', '^customer/add/$', '^customer/edit/(?P<cid>\\d+)/$', '^customer/del/(?P<cid>\\d+)/$', '^customer/import/$', '^customer/tpl/$', '^payment/list/$', '^payment/add/$', '^payment/edit/(?P<pid>\\d+)/$', '^payment/del/(?P<pid>\\d+)/$']
注意:这里面的url都是正则表达式!通过它来验证用户的url是否授权!
登录页面
先做用户登录
修改web目录下的urls.py,增加路径
from django.conf.urls import url
from web.views import customer,payment,auth,login urlpatterns = [
# 客户管理
url(r'^customer/list/$', customer.customer_list),
url(r'^customer/add/$', customer.customer_add),
url(r'^customer/edit/(?P<cid>\d+)/$', customer.customer_edit),
url(r'^customer/del/(?P<cid>\d+)/$', customer.customer_del),
url(r'^customer/import/$', customer.customer_import),
url(r'^customer/tpl/$', customer.customer_tpl),
# 账单管理
url(r'^payment/list/$', payment.payment_list),
url(r'^payment/add/$', payment.payment_add),
url(r'^payment/edit/(?P<pid>\d+)/$', payment.payment_edit),
url(r'^payment/del/(?P<pid>\d+)/$', payment.payment_del),
# 登录相关
url(r'^$', login.login), # 前端
url(r'^login/$', login.login),
url(r'^auth/$', auth.AuthView.as_view({'post': 'login'})), # 认证api
]
在web目录下的views目录下,创建文件login.py
from django.shortcuts import render, redirect,HttpResponse def login(request):
return render(request,"login.html")
使用session
在web目录下的views目录下,创建文件auth.py
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
from rbac import models
from utils.response import BaseResponse class AuthView(ViewSetMixin,APIView):
authentication_classes = [] # 空列表表示不认证<span style="color: #0000ff;">def</span> login(self,request,*args,**<span style="color: #000000;">kwargs):
</span><span style="color: #800000;">"""</span><span style="color: #800000;">
用户登陆认证
:param request:
:param args:
:param kwargs:
:return:
</span><span style="color: #800000;">"""</span><span style="color: #000000;">
response </span>= BaseResponse() <span style="color: #008000;">#</span><span style="color: #008000;"> 默认状态</span>
<span style="color: #0000ff;">try</span><span style="color: #000000;">:
user </span>= request.data.get(<span style="color: #800000;">'</span><span style="color: #800000;">username</span><span style="color: #800000;">'</span><span style="color: #000000;">)
pwd </span>= request.data.get(<span style="color: #800000;">'</span><span style="color: #800000;">password</span><span style="color: #800000;">'</span><span style="color: #000000;">)
</span><span style="color: #008000;">#</span><span style="color: #008000;"> print(user,pwd)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 验证用户和密码</span>
obj = models.UserInfo.objects.filter(name=user,password=<span style="color: #000000;">pwd).first()
</span><span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span> obj: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断查询结果</span>
response.code = 1002<span style="color: #000000;">
response.error </span>= <span style="color: #800000;">'</span><span style="color: #800000;">用户名或密码错误</span><span style="color: #800000;">'</span>
<span style="color: #0000ff;">else</span><span style="color: #000000;">:
role </span>= obj.roles.all() <span style="color: #008000;">#</span><span style="color: #008000;"> 查询当前用户的所有角色</span>
permissions_list = [] <span style="color: #008000;">#</span><span style="color: #008000;"> 定义空列表</span> <span style="color: #0000ff;">for</span> i <span style="color: #0000ff;">in</span> role: <span style="color: #008000;">#</span><span style="color: #008000;"> 循环角色</span>
per = i.permissions.all() <span style="color: #008000;">#</span><span style="color: #008000;"> 查看当前用户所有角色的所有权限</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print(i.permissions.all())</span>
<span style="color: #0000ff;">for</span> j <span style="color: #0000ff;">in</span><span style="color: #000000;"> per:
</span><span style="color: #008000;">#</span><span style="color: #008000;"> print(j.url)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 将所有授权的url添加到列表中</span>
permissions_list.append(j.url)
</span><span style="color: #008000;">#</span><span style="color: #008000;"> print(permissions_list)</span>
response.code = 1000 <span style="color: #008000;">#</span><span style="color: #008000;"> 增加session</span>
request.session[<span style="color: #800000;">'</span><span style="color: #800000;">url</span><span style="color: #800000;">'</span>] =<span style="color: #000000;"> permissions_list </span><span style="color: #0000ff;">except</span><span style="color: #000000;"> Exception as e:
response.code </span>= 10005<span style="color: #000000;">
response.error </span>= <span style="color: #800000;">'</span><span style="color: #800000;">操作异常</span><span style="color: #800000;">'</span> <span style="color: #008000;">#</span><span style="color: #008000;"> print(response.dict)</span>
<span style="color: #0000ff;">return</span> Response(response.dict)</pre>
在web目录下的templates目录下,创建login.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="{% static 'js/jquery-3.3.1.min.js' %} "></script>
<script src="{% static 'plugins/sweetalert/sweetalert-dev.js' %} "></script>
<link rel="stylesheet" href="{% static 'plugins/sweetalert/sweetalert.css' %}">
</head>
<body>
<div style="height: 100px;"></div>
<form action="/auth/" method="post">
<lable>用户名</lable>
<input type="text" name="username" id="user">
<lable>密码</lable>
<input type="password" name="password" id="pwd">
<input type="button" id="sub" value="登录">
</form>
<script>
$("#sub").click(function () {
$.ajax({
url: "/auth/",
type: "post",
data: {
username: $("#user").val(),
password: $("#pwd").val(),
},
success: function (data) {
console.log(data);
if (data.code == 1000) { //判断json的状态
swal({
title: '登录成功',
type: 'success', //展示成功的图片
timer: 500, //延时500毫秒
showConfirmButton: false //关闭确认框
}, function () {
window.location.href = "/customer/list/"; //跳转
});
} else {
swal("登录失败!", data.error,
"error");
{#window.location = "/backend/add_category/";#}
}
},
error: function (data) {
console.log('登录异常');
}
})});
</script>
</body>
</html>
在web目录下的templates目录下,创建error.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="{% static 'js/jquery-3.3.1.min.js' %} "></script>
{#<link rel="stylesheet" href="http://mishengqiang.com/sweetalert/css/sweetalert.css">#}
<link rel="stylesheet" href="{% static 'plugins/sweetalert/sweetalert.css' %}">
{#<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>#}
<script src="{% static 'js/jquery-3.3.1.min.js' %}"></script>
{#<script src="http://mishengqiang.com/sweetalert/js/sweetalert-dev.js"></script>#}
<script src="{% static 'plugins/sweetalert/sweetalert-dev.js' %}"></script>
<div>
{#获取错误信息#}
<input type="hidden" id="msg" value="{{ msg }}">
<input type="hidden" id="url" value="{{ url }}">
</div> <script>
$(function () {
var msg = $("#msg").val();
var url = $("#url").val();
console.log(msg);
console.log(url);</span><span style="color: #0000ff;">if</span> (msg.length > 0) { //<span style="color: #000000;">判断是否有错误信息
swal({
title: msg,
text: </span><span style="color: #800000;">"</span><span style="color: #800000;">1秒后自动关闭。</span><span style="color: #800000;">"</span><span style="color: #000000;">,
type: </span><span style="color: #800000;">'</span><span style="color: #800000;">error</span><span style="color: #800000;">'</span><span style="color: #000000;">,
timer: </span>1000<span style="color: #000000;">,
showConfirmButton: false
}, function () {
window.location.href </span>= url; //<span style="color: #000000;">跳转指定url
}); } })
</script>
</body>
</html>
中间件验证
在web目录下创建文件middlewares.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, redirect, HttpResponse
from luffy_permission import settings
import os class AuthMD(MiddlewareMixin): # 验证登录
white_list = ['/','/login/','/auth/','/admin/' ] # 白名单
# black_list = ['/black/', ] # 黑名单
ret = {"status": 0, 'url': '', 'msg': ''} # 默认状态<span style="color: #0000ff;">def</span> process_request(self, request): <span style="color: #008000;">#</span><span style="color: #008000;"> 请求之前</span>
request_url = request.path_info <span style="color: #008000;">#</span><span style="color: #008000;"> 获取请求路径</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> get_full_path()表示带参数的路径</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print(request.path_info, request.get_full_path())</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 判断请求路径不在白名单中</span>
<span style="color: #0000ff;">if</span> request_url <span style="color: #0000ff;">not</span> <span style="color: #0000ff;">in</span><span style="color: #000000;"> self.white_list:
</span><span style="color: #0000ff;">import</span><span style="color: #000000;"> re
per_url </span>= request.session.get(<span style="color: #800000;">"</span><span style="color: #800000;">url</span><span style="color: #800000;">"</span>) <span style="color: #008000;">#</span><span style="color: #008000;"> 获取用户session中的url列表</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print(per_url)</span>
<span style="color: #0000ff;">if</span><span style="color: #000000;"> per_url:
</span><span style="color: #0000ff;">for</span> i <span style="color: #0000ff;">in</span> per_url: <span style="color: #008000;">#</span><span style="color: #008000;"> 循环url列表</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 使用正则匹配。其中i为正则表达式,request_url.lstrip('/')表示去除左边的'/'</span>
result = re.match(i, request_url.lstrip(<span style="color: #800000;">'</span><span style="color: #800000;">/</span><span style="color: #800000;">'</span><span style="color: #000000;">))
</span><span style="color: #008000;">#</span><span style="color: #008000;"> print(result)</span>
<span style="color: #0000ff;">if</span> result: <span style="color: #008000;">#</span><span style="color: #008000;"> 判断匹配结果</span>
<span style="color: #0000ff;">print</span>(<span style="color: #800000;">'</span><span style="color: #800000;">授权通过</span><span style="color: #800000;">'</span><span style="color: #000000;">,request_url)
</span><span style="color: #0000ff;">return</span> None <span style="color: #008000;">#</span><span style="color: #008000;"> return None表示可以继续走下面的流程</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> else:</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print('授权不通过',request_url)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> # return redirect('/login/')</span> <span style="color: #008000;">#</span><span style="color: #008000;"> 错误页面提示</span>
self.ret[<span style="color: #800000;">'</span><span style="color: #800000;">msg</span><span style="color: #800000;">'</span>] = <span style="color: #800000;">"</span><span style="color: #800000;">未授权,禁止访问!</span><span style="color: #800000;">"</span><span style="color: #000000;">
self.ret[</span><span style="color: #800000;">'</span><span style="color: #800000;">url</span><span style="color: #800000;">'</span>] = <span style="color: #800000;">"</span><span style="color: #800000;">/login/</span><span style="color: #800000;">"</span><span style="color: #000000;">
path </span>= os.path.join(settings.BASE_DIR, <span style="color: #800000;">'</span><span style="color: #800000;">web/templates/error.html</span><span style="color: #800000;">'</span><span style="color: #000000;">),
</span><span style="color: #0000ff;">return</span> render(request, path, self.ret) <span style="color: #008000;">#</span><span style="color: #008000;"> 渲染错误页面</span></pre>
在中间件中,只要return none,就会进入下一个中间件!
修改settings.py,注册中间件
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',
'web.middlewares.AuthMD', # 自定义中间件AuthMD
]
测试登录,访问页面
http://127.0.0.1:8000/login/
访问一个不存在url
完整代码,请查看github
https://github.com/987334176/luffy_permission/archive/v1.1.zip
沈阳润才教育CRM的更多相关文章
- 自定义CRM系统
写在前面 之前在windows上写代码逻辑.搞前端等花了很长时间,跑通之后一直没往centos上部署, 昨天尝试部署下,结果发现静态文件找不到 =='' 由于写了2个组件: - arya model的 ...
- ZT ---- 给孩子的信(孩子写给爸爸妈妈的信在24、25、26楼)
胡同口 > 情感 > 婚后空间 > 给孩子的信(孩子写给爸爸妈妈的信在24.25.26楼) 给孩子的信(孩子写给爸爸妈妈的信在24.25.26楼)分享: 腾讯微博 新浪微博 QQ空间 ...
- MCtalk对话学吧课堂:真正的K12在线教育才刚刚开始
课堂之外的在线教育已经被大部分家庭所熟知,既涌现出了VIPKID等行业独角兽,也有大量致力于科技改变教育的新兴机构获得了快速成长.成立于2014年的学吧课堂就是专注在K12在线教育领域的创新机构,他们 ...
- 教育行业CRM项目开发
项目开发流程 需求分析 存储所有的客户咨询信息 避免重复数据 客户多次跟踪记录 客户来源分析.成单率分析 每个销售只能修改自己的客户信息 报名流程开发 班级 ...
- CRM系统推动教育行业数字化转型
目前,教育培训的潜在市场规模巨大,并且保持着迅猛的发展态势.同时,随着众多外资企业不断涌入中国市场,与国内大大小小的培训机构展开竞争,所以教育行业的竞争也是非常的激烈.传统的教育行业亟待数字化转型,才 ...
- odoo:开源 ERP/CRM 入门与实践
看了这张图,或许你对odoo有了一些兴趣. 这次就是和大家一起交流开源ERP/CRM系统:odoo 对以下读者有帮助:研发.产品.项目.市场.服务.运营.管理等. 一.背景趋势 社交网络.电商O2O: ...
- Django项目——CRM
一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后面陆续加上一些操作, ...
- odoo:开源 ERP/CRM 入门与实践 -- 上海嘉冰信息技术公司提供咨询服务
odoo:开源 ERP/CRM 入门与实践 看了这张图,或许你对odoo有了一些兴趣. 这次Chat就是和大家一起交流开源ERP/CRM系统:odoo 对以下读者有帮助:研发.产品.项目.市场.服务. ...
- crm项目整理
crm项目整理 一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后 ...
随机推荐
- linux 初识系统分区
- cxf动态调用外部web service 报告异常java.lang.NoSuchFieldError: QUALIFIED
原因:cxf 依赖的xmlschema-core 与xfire-all依赖的xmlschema冲突.(百度搜索亦得知:cxf 依赖的xmlschema-core 与axis2-kernel依赖的xml ...
- springboot中spring.profiles.active来引入多个properties文件 & Springboot获取容器中对象
1. 引入多个properties文件 很多时候,我们项目在开发环境和生成环境的环境配置是不一样的,例如,数据库配置,在开发的时候,我们一般用测试数据库,而在生产环境的时候,我们是用正式的数据, ...
- 连接字符串配置在App.config中
<?xml version="1.0" encoding="utf-8"?> <configuration> <connectio ...
- HDOJ 1217 Arbitrage (最短路)
题意:每两种货币之间都有不同的汇率 如果换回自己最后是赚的 输出Yes 否则是No 因为最多只有三十种货币 所以用Floyd是可行的 与一般的最短路板子不同的地方 汇率是要乘而不是加 如果乘上一个小 ...
- 国产 WEB UI 框架 (收费)-- Quick UI,Mini UI
国产 WEB UI 框架 (收费)-- Quick UI,Mini UI : http://www.uileader.com/ http://www.miniui.com/
- opencv处理验证码python代码
# -*- coding: utf-8 -*- # @Time : 2019-02-11 09:39 # @Author : cxa # @File : bgr2gry.py # @Software: ...
- ES6学习笔记七Generator、Decorators
Generator异步处理 { // genertaor基本定义,next()一步步执行 let tell=function* (){ yield 'a'; yield 'b'; return 'c' ...
- 使用mysql自带工具mysqldump进行全库备份以及source命令恢复数据库
mysql数据库提供了一个很好用的工具mysqldump用以备份数据库,下面将使用mysqldump命令进行备份所有数据库以及指定数据库 一.mysqldump一次性备份所有数据库数据 /usr/lo ...
- 通信——基于Xmpp协议实现的聊天室
前段时间写了个自定义通信协议的聊天室(即用\r\n标记字符串,作为一句话),总感觉自己弄的那个协议实现虽然简单,但是拓展性就太差了,只适合于发送聊天的内容,难以包含更多的信息.基于上述几点,于是就开始 ...