CRM系统开发,主要目标及步骤
- 权限
- stark组件
- crm业务
第一部分:权限组件
1. 创建django project
2. 两个app
- rbac,权限组件
- web,销售管理系统
3. app:rbac
-
将权限相关的表编写到此app的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) def __str__(self): return self.title class Role(models.Model): """ 角色 """ title = models.CharField(verbose_name='角色名称', max_length=32) permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permission', blank=True) def __str__(self): return 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) def __str__(self): return self.name
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
4. app:web
- 将销售管理系统表写到此app的models.py中
- 销售系统的业务相关代码:luffy_permission(示例二)
5. 两个app的整合
销售管理系统中的URL:
客户管理
客户列表:/customer/list/
添加客户:/customer/add/
删除客户:/customer/list/(?P\d+)/
修改客户:/customer/edit/(?P\d+)/
批量导入:/customer/import/
下载模板:/customer/tpl/
账单管理
账单列表:/payment/list/
添加账单:/payment/add/
删除账单:/payment/del/(?P\d+)/
修改账单:/payment/edit/\d+/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
5.1 基于admin进行权限信息的录入
5.2 基于admin进行权限和角色信息的分配
6. 快速完成一个基本权限控制
1. 登录页面是否有权限访问。
2. POST请求,用户登录检验是否合法。
3. 获取当前用户相关的所有权限并放入session。
4. 再次向服务端发起请求:http://www.xxx.com/xxx,后端编写中间件对用户当前访问的url进行权限的判断(是否在session中)
- 1
- 2
- 3
- 4
7. 功能的完善,将权限相关的功能放到rbac应用下,以便以后组件的应用。
a. 用户登录和权限初始化拆分
b. 配置文件应用
总结:6/7属于进行权限控制8
- 1
- 2
- 3
8. 动态菜单的功能
-
一级菜单,如何实现动态显示菜单?
a. 表结构修改 b. 获取菜单信息并保存到session c. 模板中显示菜单信息(session)
- 1
- 2
- 3
-
二级菜单
a. session中存储的菜单信息结构:
{ 1:{ title:'信息管理', icon:'x1', children:[ {'title':'客户列表','url':'/customer/list/'}, {'title':'帐单列表','url':'/account/list/'}, ] }, 2:{ title:'用户信息', icon:'x1', children:[ {'title':'个人资料','url':'/userinfo/list/'}, ] } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
b. 数据库表结构的修改
class Menu(models.Model): """ 菜单表 """ title = models.CharField(verbose_name='菜单名称', max_length=32) icon = models.CharField(verbose_name='图标', max_length=32) def __str__(self): return self.title class Permission(models.Model): """ 权限表 """ title = models.CharField(verbose_name='标题', max_length=32) url = models.CharField(verbose_name='含正则的URL', max_length=128) name = models.CharField(verbose_name='URL别名', max_length=32, unique=True) menu = models.ForeignKey(verbose_name='所属菜单', to='Menu', null=True, blank=True, help_text='null表示不是菜单;非null表示是二级菜单',on_delete=models.CASCADE) pid = models.ForeignKey(verbose_name='关联的权限', to='Permission', null=True, blank=True, related_name='parents', help_text='对于非菜单权限需要选择一个可以成为菜单的权限,用户做默认展开和选中菜单',on_delete=models.CASCADE) def __str__(self): return self.title
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
c. 页面显示二级菜单
inclusion_tag中循环显示 开发二级菜单:
- 1
- 2
9. 点击非菜单的权限时,默认选中或默认展开。
当点击某个不能成为菜单的权限时,指定一个可以成为菜单的权限,让其默认选中以及展开。
a. 数据库设计
b. 思路
-
登录,做权限和菜单的初始化:
- 获取菜单信息
{ 1:{ 'title':'信息管理', 'icon':'fa-camera-retro', 'class':'', 'children':[ {'url':'/customer/list/','title':'客户列表',class='active'} # 可以做菜单的权限ID ] } 2:{ 'title':'用户管理', 'icon':'fa-fire', 'class':'hide', 'children':[ {'url':'/payment/list','title':'帐单列表'} ] } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 获取权限信息
[ {'id':1,'url':'/customer/list/','pid':null}', # 客户列表,可做菜单的 {'id':2,'url':'/customer/add/','pid':1}', # 添加客户,不可 {'id':3,'url':'/customer/del/(?
\d+)' ,'pid':1}', # 删除客户,不可 ]- 1
- 2
- 3
- 4
- 5
-
再次来访问
- 中间件进行权限的校验(根据权限信息)
获取ID或PID(应该被选中的可以做菜单的权限ID)
- 中间件进行权限的校验(根据权限信息)
-
模板中使用inclusion_tagshengcheng动态菜单(根据菜单信息进行动态生成)
10. 路径导航
11. 权限力度控制到按钮级别
总结:
- 权限控制
- 动态菜单
- 权限的分配
问题:以前你是如何做的权限分配?被某个用户分配一个角色?某个任分配某个权限。
答案:django admin进行录入
12. 权限分配
a. 角色管理
- ModelForm
- 根据 namespace 和 name 反向生成URL
- 模板的查找顺序
b. 用户管理
- ModelForm
- 字段的自定制
- 钩子方法
- 错误提示(中文)
- 重写__init__方法,统一给所有字段添加属性(form-control)
- 根据 namespace 和 name 反向生成URL
- 模板的查找顺序
c. 菜单和权限管理
视频讲解:
- 一级
- 二级
- 权限
知识点:
- 保留URL中的原搜索条件
- 模板中整形转换成字符串 1|safe
- ModelForm定制radio
- ModelForm显示默认值
- ModelForm save之前对其instance进行修改
- BootStrapModelForm基类
d. 批量的权限操作
- formset
- 什么是formset?
答:Form组件或ModelForm用于做一个表单验证。用于做多个表单验证的组件。 - 应用场景?
答:批量操作。 - 如何实现用formset?
答:见示例代码
- 什么是formset?
- 自动发现项目中的URL
- 问题:给你一个项目,请帮我获取当前项目中都有哪些URL以及name rbac:permission_list
- 实现思路。
- 具体实现:见实例代码。
- 权限的批量操作
- 知识点
- formset(ModelFormSet)
- 自动发现项目中的URL
- 唯一约束的错误信息
e. 分配权限
- 展示用户、角色、权限信息
- 选择用户、角色时,页面上的默认选项。
- 角色和权限分配[保存]
- 知识点的总结:
-
数据类型设置引用
menu_list=[ {'id':1,'title':'菜单1'}, {'id':2,'title':'菜单2'}, {'id':3,'title':'菜单3'}, ] menu_dict={} """ menu_dict={ 1:{'id':1,'title':'菜单1'}, 2:{'id':2,'title':'菜单2'}, 3:{'id':3,'title':'菜单3'}, } """ for item in menu_list: munu_dict[item['id']]=item # menu_dict[2]['title']='666' menu_dict[2]['children']=[11,22] print(menu_list)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
-
13. 编写使用文档(主机管理程序)
第二部分:stark组件
介绍:
stark组件,是一个帮助开发者快速实现数据库表的增删改查+。
- 1
目标:
10s中完成一张表的增删改查
- 1
前戏:
1. django项目启动时,自定义执行某个py文件。
django启动时,且在读取项目中路由之前执行某个py文件。
在任意app的apps.py中的Config类中定义ready方法,并调用
- 1
- 2
from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules
class App01Config(AppConfig):
name = 'app01'
def ready(self):
autodiscover_modules('文件名')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
django在启动时,就会去已注册的所有app的目录下找xxxx.py,并自动导入。
如果执行两次,是因为django内部自动重启导致:
- 1
- 2
python manage.py runserver 127.0.0.1:8000 --noreload
- 1
提示:
如果xxxx.py执行的代码向"某个神奇的地方"放入了一些值,之后的路由加载时,可以去"某个神奇的地方"读取到原来设置的值.
- 1
- 2
2. 单例模式
单,一个
例,实例,对象。
通过利用Python模块导入的特性:在Python中,如果已经导入过的文件再次被重新导入时,python不在重新解释一遍,二十选择从内存中直接将原来的导入的值拿来用。
- 1
- 2
- 3
- 4
xxx.py
class AdminSite(object):
pass
site=AdminSite()#为AdminSite类创建了一个对象(实例)
app.py
import utils
print(utils.site)
import utils
print(utils.site)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
提示:
如果以后存在一个单实例模式的对象,可以先在此对象中放入一个值,然后再在其他的文件中导入对象,通过对象再次将值获取到。
- 1
- 2
3. django路由分发的本质:include
方式一:
from django.conf.urls import url,include
urlpatterns=[
url(r'^web/',include("app01.urls")),
]
- 1
- 2
- 3
- 4
- 5
方式二:
include函数主要返回有三个元素的元组。
- 1
from django.conf.urls import url,include
from app01 import urls
urlpatterns=[
url(r'^web/',(urls,app_name,namespace)), # 第一个参数时urls文件对象,通过此对象可以获取urls.patterns获取分发的路由。
]
- 1
- 2
- 3
- 4
- 5
在源码内部,读取路由时:
如果第一个参数有:urls.patterns属性,那么子路由就从该属性中获取。
如果第一个参数无:urls.patterns属性,那么子路由就是第一个参数。
- 1
- 2
- 3
方式三:
urlpatterns=[
url(r'^web/',([
],app_name,namespace)), #第一个参数是urls文件对象,通过此对象可以获取urls.patterns获取分发的路由。
]
- 1
- 2
- 3
- 4
- 5
示例:pre_luffy_stark.zip
- 1
开始:
1. 创建django project
2. 创建基础的业务表:
app01/models.py
部门表
用户表
app02/models.py
主机表
- 1
- 2
- 3
- 4
- 5
3. 对以上的三张表做增删改查
a. 分析
-
为每张表创建4个url
-
为每张表创建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 /app01/host/list/ /app01/host/add/ /app01/host/edit/(\d+)/ /app01/host/del/(\d+)/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
b. 为app中的每个model类自动创建URL及相关试图函数
- 动态生成URL
- 将试图提取到基类
- URL分发扩展 & 后缀
- 为URL设置别名
- 为URL设置别名
c. 定制页面显示的列
- 基本列表页面列的定制
- 未定义list_display字段的页面,默认显示对象
- 为页面显示的列预留一个钩子函数
- 为页面提供自定义显示的函数
- 应用
d. 应用模板样式(BootStrap)
e. 列表页面添加分页的功能
f. 添加
- 如何显示添加按钮
- 添加按钮的URL
- 添加页面进行添加数据
g. 编辑
- 编辑按钮(删除按钮)
- 页面操作
h. 删除
4. 其他常用功能
a. 排序
b. 模糊搜索
- 实现思路:
在页面是设置form表单,搜索:以Get形式提交请求到后台,后台获取数据然后进行筛选过滤。
后端获取到关键字之后,根据定义的列进行查找(多列可以按照或进行查询)。 - Q
c. 批量操作
- 增加checkbox列
- 生成批量操作的"按钮"
d. 组合搜索
- 什么是组合搜索?
- 如何实现组合搜索?
- 实现思路,根据字段找到其相关联的数据:choice、FK、M2M
- 第一步:配置
- 第二步:根据配置获取关联数据
- 第三步:根据配置获取关联数据(含条件)
- 第四步:在页面上显示组合搜索的按钮
- 将QuerySet和元组进行封装
- 第五步:为组合搜索按钮生成URL
- 生成URL时,不影响其他组的条件
- 条件筛选
- 多选
总结:
- 页面:列表、添加、编辑、删除
- 模糊搜索、批量操作、组合搜索
第三部分: crm业务开发
1. 项目背景
以教育机构为背景的crm项目,系统主要为 销售部、运营部、教质部 提供平台,对他们的工作进行量化,有利于公司信息化的建设。
-
销售部
- 公户,公共客户。
- 私户,我的客户。 <= 150人 + 跟进记录 + 入班申请(财务审核)
-
运营部
- 录入客户信息(公户)
-
教质部
- 考勤
- 学员访谈
- 积分管理
- 转班申请
2. 项目开发
2.1 概览
-
基础业务处理
- 校区管理
- 部分管理
- 用户管理
- 课程管理
- 开班管理
-
客户管理
- 公户
- 私户
-
学员管理
- 考勤
- 谈话记录
- 积分
-
rbac组件