crm笔记
大目标: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 权限应用 - 基本权限校验 - 粒度控制到按钮
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)