大目标:crm系统。
--权限组件
--stark组件
--crm业务
步骤:
第一部分权限组件:
1.创建django project,luffy-permission
2.两个app
--rbac,权限组件
--web,销售管理系统
3.app: rbac
-将权限相关的表编写到此app的models.py中
4.app:web
-将销售管理系统表写到此app的models.py中
-销售系统的业务代码
5.两个app的整合
客户管理
客户列表:/customer/list/
添加客户:/customer/add/
删除客户:/customer/del/(?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+/
那么接下来,我们就在权限组件中录入相关信息:
录入权限
创建用户
创建角色
用户分配角色
角色分配权限
6.权限控制设计思路--初始化
--减少数据库的压力,在中间件request.session中检验权限
1.登录页面是否有权限访问。 所有人都可访问
2.post请求,用户登录检验是否合法,不合法返回继续登录
3.登录成功后,获取当前用户的所有权限并放入session
4.中间件中控制:当在向服务器发起请求url时候,后端编写中间件对用户当前访问的url进行权限的判断(是否在session中)
7.功能完善,将权限相关的代码当如rbac组件中
--权限初始化代码 归类
1.登录代码和权限初始化拆分
2.settings.PERMISSION_SESSION_KEY 在设置中配置
总结:6,7权限的控制
8.动态菜单
--一级菜单 如何实现动态显示一级菜单?
a.变结构修改+录入菜单数据
b.获取菜单信息并保存到session
c.模板中显示信息 引入:inclusion_tag渲染模板
--二级菜单
a.表结构
fa-free-code-camp
fa-money
{
1:{
title:'用户信息',
icon:'x1',
chirldren:[
{title:'个人信息',url:'/userinfo/'},
]
},
2:{
title:'客户信息',
icon:'x1',
chirldren:[
{title:'客户列表',:'/userinfo/'},
]
},
}
b.表结构:
class Menu(models.Model):
"""
菜单表
"""
title =models.CharField(verbose_name='一级菜单名称',max_length=32)
icon = models.CharField(verbose_name='图标',max_length=32,blank=True,null=True)
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name='标题',max_length=32)
url = models.CharField(verbose_name='含正则的url',max_length=128)
menu= models.ForeignKey(verbose_name='所属菜单',to='Menu',on_delete=models.CASCADE,blank=True,null=True,help_text='null表示不是菜单,非null表示二级菜单')
def __str__(self):
return self.title
c.页面显示二级菜单 默认设置一级菜单隐藏 class = hide,并才css中设置具体的样式
9.点击非菜单的权限时,默认选中或默认展开
当点击某个不能成为菜单的权限时,指定一个可以成为菜单的权限,也让其默认选中以及展开
在Permission表中加自关联pid,要加一个related_name='parents'
a.数据库涉及
b.思路
-登录,做权限和菜单的初始化
--获取菜单信息
{
1:{
title:'用户信息',
icon:'x1',
chirldren:[
{id:1,title:'个人信息',url:'/userinfo/'},
]
},
2:{
title:'客户信息',
icon:'x1',
chirldren:[
{id:7,title:'客户列表',:'/userinfo/'},
]
},
}
--获取权限信息
{
{id:1,url:'/customer/list',pid=null}, 客户列表,可做菜单
{id:2,url:'/customer/add',pid=1}, #添加菜单不可做菜单,默认选pid=1的客户列表做菜单
{id:3,url:'/customer/del/(?P<cid>d+)',pid=7},
}
-再次登录时,到中间件中做校验(根据权限信息)
-从request.session中获取权限信息,id或pid
-在通过request,将pid或者id传到inclusion_tag
(request.current_selected_url=item['pid'] or item['id'])
-模板中使用动态菜单--inclusion_tag动态生成菜单(根据菜单信息)
从request.session中获取菜单信息
10.路径导航
breadcrumb
--首页/账单列表/添加账单
11.权限的粒度控制到按钮级别:
--修改数据库--加url别名name(customer_list)--->>permission_dict 以URL别名做key值
--过滤器filter可以在if后面当条件,而tag和inclusion_tag不能(自己定义一个过滤器,最多2个参数)
{% if request|has_permission:"customer_add"%}
<a class="btn btn-default" href="/customer/add/">
<i class="fa fa-plus-square" aria-hidden="true"></i> 添加客户
</a>
{% endif %}
总结:
- 权限控制
- 动态菜单
- 权限的分配
问题:以前你是如何进行权限分配的?给某个用户分配一个角色?某个人分配权限
答案:django admin进行录入
12.权限分配 先把权限校验的中间件去掉了,左边栏和导航栏也去掉了
a.角色管理 Role
--forms.ModelForm和forms.Form
from django import forms
class RoleModelForm(forms.ModelForm):
"""
角色组件
"""
class Meta:
model=models.Role
fields=['title',]
widgets={
'title':widgets.TextInput(attrs={'class':'form-control'})
}
labels = {
"title": "角色名称"
}
error_messages = {
'title':{'required':"角色名不能为空",},
}
(RoleModelForm(instance=obj,data=request.POST),编辑的需要把编辑的obj传入组件)
--include路由分发时的名称空间,和rbac.urls里的name
--django模板的查找顺序,以及add/edit模板复用,del模板复用
b.用户管理 UserInfo
--知识点:
1.forms.ModelForm
字段的新增,
钩子方法,
super,重写init方法,统一给所有字段添加属性
中文显示错误信息:配置中LANGUAGE_CODE = 'zh-hans'
2.根绝namespace和name反向生成url,在模板中和py文件中2中方式
3.模板的查找顺序
c.菜单和权限管理 Menu/Permission
---ModelForm 操作一张表
1.panel 公告框
2.保留原有搜索条件 自定义simple_tag:memory_url (类似原生url)
3.模板中整型转成字符串|safe
4.ModelForm中 forms.RadioSelect 选择框
from django.utils.safestring import mark_safe
class MenuModelForm(forms.ModelForm):
class Meta:
model = models.Menu
fields=['title','icon']
widgets = {
'title':forms.TextInput(attrs={'class':'form-control'}),
'icon':forms.RadioSelect(
choices=[
['fa-address-book-o',mark_safe('<i class="fa fa-address-book-o" aria-hidden="true"></i>')],
['fa-envelope-open',mark_safe('<i class="fa fa-envelope-open" aria-hidden="true"></i>')],
['fa-envelope-open-o',mark_safe('<i class="fa fa-envelope-open-o" aria-hidden="true"></i>')],
],
attrs={'class':'clearfix'}
)
}
5.ModelForm中 下拉框设置默认值
menu_object = models.Menu.objects.filter(pk=menu_id).first() #为了能设置默认值。需要一级菜单的id
form = SecondMenuModelForm(initial={'menu':menu_object})
6.ModelForm中 save之前 在数据库中设置二级菜单 form.instance.pid = seconde_menu_obj #在数据库里默认添加二级菜单
7.BootstropModelForm 自定义样式定制
d.权限的批量操作
--formset
什么是formset?
答:Form组件或ModelForm用于做一个表单验证(数据库的一张表里对应的一条数据)
formset:指的是可以用与多个表单的验证组件
应用场景?
--批量操作
--自动发现所有URL (from django.urls import URLResolver,URLPattern)
--问题:找到项目中的所有url
{
'rbac:menu_list:{name:'rbac:menu_list',url:'rbac/menu/list'}
}
--批量的权限操作
思路:
1.获取项目中所有的权限 set1
2.去数据库中获取已经录入的所有权限 set2
情况1::自动发现的 >数据库中的 -->实现批量添加 ps:通过name进行比对(model中设置唯一)
set1 - set2 ==>添加 formset
情况2:数据中的 > 自动发现 -->实现批量删除
set2 - set1 ==>删除
情况3: 自动发现的 > 数据库有的 --实现批量更新
set3 = set1 & set2 ==>更新 formset
e.权限分配
--展示用户/角色/权限信息
--选择用户/角色时,页面上的默认选项
--角色和权限分配【保存】
列表==>赋值给字典--引用同一块内存地址
rbac使用文档README
第二部分stark组件:
介绍:stark组件,是一个帮助开发者快速实现数据库表的增删改查
目标:10s 完成一张表的增删改查
前戏:
1.django项目启动时,自定义执行某个文件
在django项目启动前,且在读取路由加载前,执行某个py文件
在 任意的 app的apps.py中的Config类,定义ready方法,调用autodiscover_modules
from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules
class App01Config(AppConfig):
name = 'app01'
def ready(self):
autodiscover_modules('xxx')
django在启动前,就会去已经注册的app的目录下找xxx.py并自动执行
如果执行两次,是因为django内部自动重启导致,2个线程,一个时启动项目,另一个看代码更新状态
python manage.py runserver 127.0.0.1:8001 --noreload #只执行一次
提示:
如果xxx.py执行的代码,向其他地方放入了一些值,之后的路由加载时,可以去那里读取
2.单例模式
单:一个
例:实例,对象
通过利用python模块导入的特性,如果已经导入的模块在被重新导入时,python不会在重新解释一遍,而是选择从内存中读取原来导入的值
提示:
如果以后存在一个单例模式的对象,可以先在此对象中放入一个值,
然后在其他的文件中导入该对象,通过对象再次,将值获取到
3.django路由分发的本质include
re_path(r'^rbac/', include(([
re_path(r'^role/list/$', role.role_list,name='role_list'), # rbac:role_list
re_path(r'^role/add/$', role.role_add,name='role_add'),
], 'rbac'),namespace='rbac')),
--- urlconf_module, app_name, namespace
开始!
1.创建一个project
2.创建基础业务表
app01/models.py
用户表
部门表
app02/models.py
主机表
3.对 以上三张表做增删改查
a.为每张表创建4个url
b.为每张表创建4个视图函数
app01/models.py
Depart
/app01/depart/list/
/app01/depart/add/
/app01/depart/edit/(d+)/
/app01/depart/del/(d+)/
UserInfo
/app01/userinfo/list/
/app01/userinfo/add/
/app01/userinfo/edit/(d+)/
/app01/userinfo/del/(d+)/
app02/models.py
Host
/app02/host/list/
/app02/host/add/
/app02/host/edit/(d+)/
/app02/host/del/(d+)/
为app中的每个model类 自动创建url以及视图函数
- 动态生成url
- 视图提取到基类
- URL&分发扩展 &后缀
- URL设置别名name
- URL的别名进行重新的生成 优化
c.定制html页面显示的列
- 基本完成列表页面的定制
- 未定义list_display字段的页面,默认显示对象
- 为页面显示的列预留一个钩子函数 扩展
- 页面自定义显示的列的函数
d.应用模板样式(layout.html/bootstarp)
e.分页功能
f.添加按钮
- 如何显示添加按钮
- 添加按钮的url
- 添加界面进行添加数据(保留原搜索条件)
g.编辑
- 编辑按钮
- 页面操作
h.删除
4.其他功能
- 排序
- 模糊搜索
- 实现思路:
在页面上设置form表单,已get形式提交搜索条件到后台,后台获取数据,
进行数据筛选,根据自定义的列表search_list进行查找(多列可以按照或进行查询(crm中Q语法))
- 动态搜索
- 批量操作
- 添加checkbox列
- 生成批量操作的按钮
- 组合搜索
- 什么是组合搜索?
- 如何实现?
- 实现思路:根据字段找到与其关联的数据:choice、foreginkey、manytomany
- 1.配置 search_group = ['gender','depart'] #想要分2组
- 2.根据配置获取到数据
- 3.跟据配置获取到数据(含条件)
- 4.在页面上显示组合搜索的按钮(在后台生成html代码)
将queryset_or_tuple进行封装
-5.为组合搜索按钮生成URL
-6.多选搜索
总结: - 页面:了,列表、添加、编辑、删除
- 模糊搜索、批量操作、组合搜索
第三部分:crm业务开发
1.项目背景介绍:
以教育机构为背景的crm项目,系统主要为销售部、运营部、教质部、提供平台,对他们的工作进行量化
销售部:
- 公户,公共用户
- 私户,我的用户。 <=150人 +跟进记录+入班申请(财务审核)
运营部:
- 录入客户信息(公户)
教质部:
- 考勤
- 学院访谈
- 积分管理
- 转班申请
2.项目开发
2.1 概况
- 基础业务处理
- 校区管理
- 部门管理
- 用户管理
- 课程管理
- 开班管理
- 客户管理
- 公户
- 私户
- 学员管理
- 考勤
- 谈话记录
- 积分
- rbac组件
2.2
- 2.2.1 创建项目
- 2.2.2 校区管理
- 2.2.3 部门管理
- 2.2.4 用户管理
- 页面基本操作 添加 编辑 删除
- 添加页面需要新增一个确认字段 $编辑页面删除密码字段
- 重置密码
- 新加一条路由 (用预留的钩子extra_url)
- 加视图、前端界面、保留原搜索条件(反向生成url)
- 页面功能的增加(模糊搜索、组合搜索)
- 2.2.5 客户管理+代码的拆分到views中
- 2.2.6 班级管理
- 班级管理基本操作(定制display_course显示列)
- 基于limit_choice_to 对于关联的Fk,M2M进行筛选
limit_choices_to={'depart__title__in':['Linux教学部','Python教学部']}
- 班级管理时间插件的应用(stark组件新增DateTimePickerInput插件、
【from stark.forms.DateTimePickerInput import DateTimePickerInput】)
- 2.2.7 客户管理
- 公户
- 公户基本管理:公户列表、录入客户
- 查看跟进记录
- 批量申请到私户:个数限制、数据库中事务加锁、添加当前登录人(即为我的私户)
- 用户登录 后将user_id存到session中,后续取的时候从session中获取
- 私户
- 私户基本管理 添加时客户顾问默认是登录人自己,在数据库中添加(预留的钩子save)
- 私户剔到公户
- 跟进记录管理 -- 根据strark组件生成url
- 查看
- 添加
- 编辑
- 删除
- 缴费&报名
- 业务分析
- 学员缴费
- 课程顾问:提交缴费申请
- 财务:审核(状态更新、入班学习)
- 代码实现
- 表结构设计
- 查看缴费列表
- 添加缴费记录
- 缴费审批
- 2.2.8 学员管理
- 学生管理
- 积分管理
- 考勤管理
- 上课记录
- 考勤记录
- 2.2.9 权限应用
- 基本权限校验
- 粒度控制到按钮