CRM项目问答总结
- 1. 通过ChangeList封装好多数据
- DA:
- 在stark组件中,有五个封装的大类:
- class FilterOption(object): ----用于封装组合搜索的配置信息(数据库字段,是否多选,是否是choice)
- class FilterRow(object):----生成按钮以及一系列的<a>标签
- class ChangeList(object):----将列表页面的功能封装到此类中
- class StarkConfig(object):----用于为每个类生成url的对应关系,并处理用户请求,处理增删改查的基类
- class StarkSite(object):----是一个容器,用于放置处理请求的对应关系
- 2. 销售中公共资源:Q查询,3天 15天
- DA:如果有新用户引进,对于销售来说,必须得跟进,但是跟进的过程中会有3天未跟进,15天未成单的限制。
- 如果该客户成为了公共资源,那么就会有抢单这一功能。在实现抢单时,一般的数据查询在这里不太适用,所有这里引用到Q查询,更高效的查出结果
- Q:查询函数可以混合使用 Q 对象参数和关键字参数. 所有提供给查询函数的参数(不管是关键字参数还是Q对象)都被 "AND" 到一起.
- 如果提供了 Q 对象作为参数,它就必须在其它关键字参数(如果有的话)的前面
- 3. 使用yield实现
- - 生成器函数,对数据进行加工处理
- DA:在ChangeList中,def gen_comb_filter(self): 给前端进行循环显示数据用(生成器函数),
- 在生成器中返回可迭代对象,FilterRow对象(FilterRow对象是自己创建的)
- - __iter__和yield配合
- 4. 获取Model类中的字段对应的对象
- class Foo(model.Model):
- xx = models.CharField()
- Foo.get_field('xx')
- 5. 模糊搜索功能
- DA:模糊搜索就是在列表页面中,增加模糊关键字搜索功能,和是否显示添加按钮,actions定制,组合搜索都封装在了StarkConfig类中。
- if key_word and self.get_show_search_form():
- for field_name in search_fields:
- condition.children.append((field_name, key_word))
- return condition
- 6. Type创建类
- DA:
- 用type创建动态的form如:
- TempForm = type('TempForm',(Form,),{
- 'score_%s' %obj.pk
- :fields.ChoiceField(choices=models.StudyRecord.score_choices),
- 'homework_note_%s' %obj.pk
- : fields.CharField(widget=widgets.Textarea())
- })
- 7. 自动派单
- DA:
- -自动派单:
- 在处理自动派单问题时应该考虑到当前用户是否为公司的公共资源,在判断公共资源这个问题上就要根据当前用户是否为已经属于公共客户:
- a:公共客户
- 所谓的公共的客户就是销售在规定的某个时间段内没有把客户转化为用户,或者没有在允许的时间内跟进,就会被转为公共用户。而成为公共用户之后,该销售则无权跟进(利用Q对象的方法进行排除),
但是也不排除,有的客户冥顽不灵,转化不了,其他的销售都不喜欢或者不愿意跟进,该销售也可以跟进。- b:自己的客户
- 所谓我的客户就是已经成单或者在规定时间内正在跟进的客户,而且在这里将会有一个客户跟进表中记录销售的跟进内容,生成一条跟进内容如果是一个新的客户的话,就设置一个定时的一个检查的脚本
,以用于查看销售的跟进记录。在新建的表里选出没有报名的用户,在没有报名的用户上加抢单功能,获取用户的ID,修改客户表中的客户,把接单时间修改为当前时间,跟进时间也是当前时间,修改客户顾问为现在的。- c:自动抢单
- 单条录入,创建url,进入用modelform写的页面,新增客户表中的数据,获取自动分配的课程顾问的ID,当前时间,在客户分配表中新增数据,获取新创建的客户ID,课程顾问ID,
而给课程顾问分配是跟据权重进行分配的- - 原来在内存中实现,问题:重启和多进程时,都有问题。
- - redis
- - 状态
- - 原来数据(权重表 权重和个数)
- - pop数据
- DA:在多选或者单选,后面必须添加popup按钮,因为如果是field是ModelChoiceField 则是Fk, 如果是ModelMultipChoice 则是M2M。编辑和增加弹出的子页面都用到了popup代码
需要重写一次,所以引入templatetags- 8. 使用 list_diplay配置
- DA:因为已经在v1.py中的的class StarkConfig类中封装了封装了前端列表定制列表页面显示的列,所有在使用时,只写数据库字段名即可
- list_display = ['title','code']
- 9. reverse反向生成URL
- DA:
- def index(request):
- from django.urls import reverse
- test_url = reverse('xxx')
- return HttpResponse("index")
- def back(requext):
- return HttpResponse("back")
- urlpatterns = [
- url(r'^index/', index,),
- url(r'^back/dd/nn/', back,name='xxx'),
- ]
- 10. 母版
- DA:
- 在最外层的templates:stark>layout.html作为模板,让其他的相关页面去继承layout.html。大大 降低了代码重复
- 11. ready方法定制起始文件
- DA:
- 就是在启动项目的同时,运用ready方法加载出来运行。
- - 文件导入实现单例模式
- 12. inclusion_tag
- 13. 中间件的使用
- -什么是中间件:
- django中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。在django项目的settings模块中,
有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件- DA:-用户登录
- - 日志记录
- - csrf
- - session
- - 权限管理
- 15. importlib + getattr
- 16. FilterOption,lambda表达式
- DA:
- lanmbda是一个匿名函数它可以通过传给reduce中的函数,依次对数据集中的数据进行操作。
- 17. QueryDict
- - 原条件的保留
- - filter
- 18. ModelForm
- DA:没有用Form,但是这里运用ModelForm创建自动生成的列表页面以及input框的错误提示信息
- 19. 面向对象的 @property @classmethod
- DA:
- @property是把一个方法变成属性可调用的
- eg:把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,
我们就拥有一个可控的属性操作(百度搜索到的说法)- @staticmethod可以不需要实例化,直接用 类名.方法名来调用
- 即:(两者的区别)
- @staticmethod不需要表示自身对象的self和自身类的cla参数,就跟使用函数一样
- @classmethod也不需要self参数,但第一个参数需要表示自身类的cls参数
- 20. mark_safe
- DA:
- 后端解析前端代码,可在前端展示成前端页面,否则是字符串形式展示
- 21. 抽象方法抽象类+raise Im...
- DA:
- 在base.py文件中运用了抽象方法
- 方法一:
- from abc import ABCMeta
- from abc import abstractmethod
- class BaseMessage(metaclass=ABCMeta):
- @abstractmethod
- def send(self,subject,body,to,name):
- pass
- 方法二:
- class BaseMessage(object):
- def send(self, subject, body, to, name):
- raise NotImplementedError('未实现send方法')
- 我们在dingding.py文件中用了抽象类
- from .base import BaseMessage
- class DingDing(BaseMessage):
- def __init__(self):
- pass
- def send(self,subject,body,to,name):
- print('钉钉消息发送成功')
- 22. 组件中的装饰器,实现self.request = request
- 23. 自执行函数
- (function(arg){
- })('sf')
- 24. URL的钩子函数
- DA:
- get_show_add_btn(self):
- ....
- 对于页面添加等按钮是否显示做出更细致的判断
- 25. 多继承
- 从左到右继承(钻石继承)
- 新式类:python3:广度优先
- 经典类:python2:深度优先
- 26. 批量导入,xlrd
- import xlrd
- file_obj = request.FILES.get('exfile')
- with open('xxxxxx.xlsx', mode='wb') as f:
- for chunk in file_obj:
- f.write(chunk)
- workbook = xlrd.open_workbook('xxxxxx.xlsx')
- sheet = workbook.sheet_by_index(0)
- maps = {
- 0: 'name',
- 1: 'qq',
- }
- for index in range(1, sheet.nrows):
- row = sheet.row(index)
- # {'name':"把几个",'qq':123456789}
- # print(row,type(row))
- row_dict = {}
- for i in range(len(maps)):
- key = maps[i]
- cell = row[i]
- row_dict[key] = cell.value
- 27. redis连接池
- DA:
- 插入单条数据
- import redis
- conn = redis.Redis(host='10.0.0.10',port=6379)
- conn.set('k1','v1') 向远程redis中写入了一个键值对
- val = conn.get('k1') 获取键值对
- print(val)
- 插入多条数据
- conn = redis.Redis(host='10.0.0.10',port=6379)
- conn.lpush('names_list',*['把几个','鲁宁'])
- v = conn.llen('names_list')
- for i in range(v):
- val = conn.rpop('names_list')
- 从右边第一条开始pop数据
- val = conn.lpop('names_list')
- 从左边第一条开始pop数据
- print(val.decode('utf-8'))
- v = conn.llen('namessssss_list')
- print(v)
- 28. 工厂模式
- settings.py
- MSG_PATH = "path.Email"
- class XXFactory(object):
- @classmethod
- def get_obj(cls):
- settings.MSG_PATH
- # rsplit
- # importlib
- # getattr
- return obj
- class Email(object):
- def send ...
- class WeChat(object):
- def send ...
- class Msg(object):
- def send ...
- 29. Models类中自定义save方法
- # 创建客户表
- #事物,如果一条失败,则全体失败
- #通过form.instance.field_name添加其它字段数据
- form.instance.consultant_id = sale_id
- form.instance.recv_date = ctime
- form.instance.last_consult_date = ctime
- new_customer = form.save()
- 30. django admin中注册models时候
- from django.contrib import admin
- from . import models
- # 方式一
- class UserConfig(admin.ModelAdmin):
- pass
- admin.site.register(models.UserInfo,UserConfig)
- # 方式二
- @admin.register(models.UserInfo)
- class UserConfig(admin.ModelAdmin):
- pass
- 31. 深浅拷贝
- DA:
- 浅拷贝copy:不管多么复杂的数据结构,浅拷贝都只会copy一层。
- 深拷贝deepcopy:其实深拷贝就是在内存中重新开辟一块空间,不管数据结构多么复杂,只要遇到可能发生改变的数据类型,
就重新开辟一块内存空间把内容复制下来,直到最后一层,不再有复杂的数据类型,就保持其
原引用。这样不管数据结构多么的复杂,数据之间的修改都不会相互影响。这就是深拷贝- 深拷贝在哪里使用过:分页
CRM项目问答总结的更多相关文章
- 某CRM项目招投标工作的感悟
最近参与了某公司的CRM项目招标工作, 由于此项目涉及到的二级单位比较多,以及项目金额比较大,所以此招标工作从准备到宣布中标一直持续了大概3个月时间,中间过程发生了一些颇有意思的事情,因为保密的原因无 ...
- CRM项目总结
CRM项目总结 一:开发背景 在公司日益扩大的过程中,不可避免的会伴随着更多问题出现. 对外 : 如何更好的管理客户与公司的关系?如何更及时的了解客户日益发展的需求变 ...
- CRM项目之RBAC权限组件-day26
写在前面 上课第26天,打卡: 世间安得双全法 不负如来不负卿 s17day26 CRM项目 项目概要:XX公司CRM - 权限管理,公共组件,app ***** - 熟悉增删改查,Low *** - ...
- 读《31天学会CRM项目开发》记录2 - 企业信息管理系统
在信息技术的快速推动下,企业如果依然利用传统的管理方式,以人为主,那效率便会大打折扣.在此背景下,企业信息化系统得 到了高速发展.如我们常见的ERP系统.MES系统,都是提高公司运行效率,降低运营以及 ...
- 读《31天学会CRM项目开发》记录1 - 认识软件开发
今天闲来无事,心中又对软件开发充满了向往和憧憬.一直认为实践是检验真知的唯一标准,也是快速提升的绝密方法,是巩固基础加深基础的好去处.故在JD上搜了下软件开发,看到了这本<31天学会CRM项目开 ...
- crm项目整理
crm项目整理 一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后 ...
- Linux下运行crm项目
虚拟环境运行crm项目 1.进入虚拟环境 2.解决crm项目运行所需的依赖环境 1.手动解决 pip3 install django==1.11.14 pip3 install pymysql pip ...
- Django - CRM项目(2)Q查询(模糊查询)
一.CRM项目(2) 利用Q查询中的q对象完成条件筛选功能. 批量删除.公户转私户功能. 新增一张跟进记录表ConsultRecord,迁移数据库并添加测试数据,实现跟进记录列表页面. 客户列表新增跟 ...
- crm项目整理概要
一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后面陆续加上一些操作, ...
随机推荐
- PHP——做服务
xml的写法和特点 <?xml version='1.0' encoding='utf-8'?><Info><code>c001</code><n ...
- dva学习---effects异步中通过select获取当前的state
根据 在组件中dispatch一个action的例子中,如果要在effects中对于param数据和当前的state数据进行再出处理,这里怎么获取state呢?采用select,如下: e ...
- 让IE6支持min-width和max-width的方法
正如君所想象的一样,同实现层的fixed一样,用的是expression语句.例如div#demo在: IE6下最小宽度300px: 或 *html div#demo { width:expres ...
- HBase MemStore与HStoreFile 的大小分析
Sumary: MemStore结构 KeyValue构成细节 HFile分析 Maven 项目例子使用了Maven来管理Dependency,要运行例子,需要有maven环境,后面提到的HFile, ...
- edmx-新建表
- 新装的Ubuntu在Nvidia显卡上分辨率不对
搜索附加驱动或者drive 然后会出现让你选择nvidia binary driver,然后点击应用更改即可.
- Java 的数组
几乎所有程序设计语言都支持数组.在C和 C++里使用数组是非常危险的,因为那些数组只是内存块.若程 序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果 (注 ...
- 【BZOJ】3016: [Usaco2012 Nov]Clumsy Cows(贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=3016 之前yy了一个贪心,,,但是错了,,就是枚举前后对应的字符(前面第i个和后面第i个)然后相同答 ...
- cobbler setting dnsmasq
Currently cobbler can help generate a ISC DHCP configuration (package name: dhcpd) it can also alter ...
- Oracle RAC功能测试
Oracle RAC是一个集群数据库,可以实现负载均衡和故障无缝切换.如何知道RAC数据库已经实现了这些功能呢,下面就对此进行功能测试. 一. 负载均衡测试RAC数据库的负载均衡是指对数据库连接的负载 ...