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系统,开始开发只是针对销售人员和客户,后面陆续加上一些操作, ...
随机推荐
- 卧槽! JavaScript JVM运行Java!!
由于任何计算机语言都具有巨大的灵活性,软件世界变得有点疯狂.一旦你已经吸收了用这种语言编写的编译器的想法,那么它会编译还有什么可以留下来的?但是......用JavaScript编写的Java虚拟机J ...
- IE下使用location对象有时会出现“没有权限”的错误
http://jadyyang.blog.sohu.com/145340845.html ——————————————————————————————————————————————————————— ...
- windows下使用c++调用redis
不废话,unix下c++调用 redis可以看这个: http://blog.csdn.net/youngqj/article/details/8266177 ==================== ...
- jfinal整合妹子UI初步完成
- Docker 和一个正常的虚拟机有何区别?
问: 我多次重读Docker.io文档,希望搞明白Docker.io和一个完全的虚拟机的区别.Docker是如何做到提供一个完整的文件系统,独立的网络环境等等这些功能,同时还没有如此庞大? 为什么部署 ...
- 关于Jquery Ajax的用法
今天简单描述一下Jquery Ajax的用法,和我在使用过程中的一些看法,仅供自己娱乐和大家参考值之用! Jquery Ajax的重要性不言而喻,只从Jquery面世之后,终于解救了像我这种既做前台又 ...
- (转)java位运算
转自:http://aijuans.iteye.com/blog/1850655 Java 位运算(移位.位与.或.异或.非) public class Test { public static ...
- hdu 4067(最小费用最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4067 思路:很神奇的建图,参考大牛的: 如果人为添加t->s的边,那么图中所有顶点要满足的条件都 ...
- 【BZOJ3439】Kpm的MC密码 Trie树+可持久化线段树
[BZOJ3439]Kpm的MC密码 Description 背景 想Kpm当年为了防止别人随便进入他的MC,给他的PC设了各种奇怪的密码和验证问题(不要问我他是怎么设的...),于是乎,他现在理所当 ...
- iOS Xcode之SVN(remove git)
项目用SVN比较多,所以大家都把精力放在如何在XCODE上使用SVN. 配置SVN当然是很简单,但提交都默认出现git的提交窗,否则要到repositories界面去提交. 目前没有找到什 ...