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项目问答总结的更多相关文章

  1. 某CRM项目招投标工作的感悟

    最近参与了某公司的CRM项目招标工作, 由于此项目涉及到的二级单位比较多,以及项目金额比较大,所以此招标工作从准备到宣布中标一直持续了大概3个月时间,中间过程发生了一些颇有意思的事情,因为保密的原因无 ...

  2. CRM项目总结

                CRM项目总结      一:开发背景 在公司日益扩大的过程中,不可避免的会伴随着更多问题出现. 对外 : 如何更好的管理客户与公司的关系?如何更及时的了解客户日益发展的需求变 ...

  3. CRM项目之RBAC权限组件-day26

    写在前面 上课第26天,打卡: 世间安得双全法 不负如来不负卿 s17day26 CRM项目 项目概要:XX公司CRM - 权限管理,公共组件,app ***** - 熟悉增删改查,Low *** - ...

  4. 读《31天学会CRM项目开发》记录2 - 企业信息管理系统

    在信息技术的快速推动下,企业如果依然利用传统的管理方式,以人为主,那效率便会大打折扣.在此背景下,企业信息化系统得 到了高速发展.如我们常见的ERP系统.MES系统,都是提高公司运行效率,降低运营以及 ...

  5. 读《31天学会CRM项目开发》记录1 - 认识软件开发

    今天闲来无事,心中又对软件开发充满了向往和憧憬.一直认为实践是检验真知的唯一标准,也是快速提升的绝密方法,是巩固基础加深基础的好去处.故在JD上搜了下软件开发,看到了这本<31天学会CRM项目开 ...

  6. crm项目整理

    crm项目整理   一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后 ...

  7. Linux下运行crm项目

    虚拟环境运行crm项目 1.进入虚拟环境 2.解决crm项目运行所需的依赖环境 1.手动解决 pip3 install django==1.11.14 pip3 install pymysql pip ...

  8. Django - CRM项目(2)Q查询(模糊查询)

    一.CRM项目(2) 利用Q查询中的q对象完成条件筛选功能. 批量删除.公户转私户功能. 新增一张跟进记录表ConsultRecord,迁移数据库并添加测试数据,实现跟进记录列表页面. 客户列表新增跟 ...

  9. crm项目整理概要

    一.开发背景 由于公司人员的增多,原来通过excel表格存取方式过于繁琐,而且对于公司人员的调配和绩效考核等不能做到精确处理,所以开发crm系统,开始开发只是针对销售人员和客户,后面陆续加上一些操作, ...

随机推荐

  1. 分析并实现 360 P1路由器上的测速功能(也可以针对金山测速功能)

    现在各种智能路由器以及一些PC上的防火墙软件,都提供网络测速功能.笔者对此进行了研究,并在自己的路由器上也实现了此功能.下面做一下总结 一般的网络测速,主要关注两个方面:网络延迟和下载速率 1.网络延 ...

  2. QT国际化,中英文等多语言界面显示的方法

    在网上学习了一下QT的国际化使用方法,最后将自己试成功的方法总结例如以下: 当中遇到的问题有:生成的ts文件里 代码中的中文 有的不显示,有的显示乱码.   步骤1: 生成.ts文件,在pro项目文件 ...

  3. Alpha matting算法发展

    一.抠图算法简介 Alpha matting算法研究的是如何将一幅图像中的前景信息和背景信息分离的问题,即抠图.这类问题是数字图像处理与数字图像编辑领域中的一类经典问题,广泛应用于视频编缉与视频分割领 ...

  4. string与wstring互转

    string与wstring互转  C++ Code  123456789101112131415161718192021222324252627282930313233343536373839404 ...

  5. VS2010程序打包操作(结合图片详细讲解)

     附视频教程:http://www.cnblogs.com/mengdesen/archive/2011/06/14/2080312.html 1.  在vs2010 选择“新建项目”----“其他项 ...

  6. AngularJS 讲解,三 过滤器

    过滤器用来格式化需要展示给用户的数据.AngularJS有很多实用的内置过滤器,同时也提供了方便的途径可以自己创建过滤器. 在HTML中的模板绑定符号{{ }}内通过|符号来调用过滤器.例如:{{va ...

  7. Leetcode-Convert Sorted Array to BST

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. So ...

  8. [LintCode] 两个排序数组的中位数

    class Solution { public: /** * @param A: An integer array. * @param B: An integer array. * @return: ...

  9. 160628、利用Oracle rownum让表排序字段值连续

    利用Oracle rownum让表排序字段值连续 1.需求说明 表(eval_index)中有字段如下: 表字段 描述 说明 ID 主键 GROUP_ID 分组编号 SORT_NUM 排序序号 按照分 ...

  10. angular做的简单购物车

    虽然本人也是刚刚才开始学习angular.js,并不是非常会,但是这并不能阻止我对angular的喜爱.因为它太省代码了,比如说一个比较简单的购物车,就是只有商品名称,单价,数量,小计,总计和删除功能 ...