CRM知识点汇总(未完💩💩💩💩💩)
一:项目中每个类的作用
- StarkSite
- 对照admin中的AdminSite,相当于一个容器,用来存放类与类之间的关系。
- 先实例化对象,然后执行该对象的register方法。将注册类添加到_register = {}中。
{
models.UserInfo:StarkConfig(models.UserInfo,self),
models.Role:StarkConfig(models.Role,self)
}
- StarkConfig
- 用来处理增删改查的基类。
- 以后每个自定义的类都需要继承的基类。
- 页面上有请求过来时,先到该类下的视图函数。
- Add_view下,要区分是否是popup添加。
- popUp链接。
- ChangeList
- 封装列表页面的功能的类。
- 以下俩类都是关于组合搜索用。
- 组合搜索时,先用到在ChangeList里面生成器函数gen_comb_filter中返回的row对象,然后在FilterRow创建__iter__方法,yield生成每个组合搜索需要的url。
- FilterRow
- 它的迭代对象为,页面上组合搜索的一行条件。
- FilterOption
- 自定义Config中,配置组合搜索的字段。(是否是多选,单选,choices。
- 看代码
- class FilterOption(object):
- def __init__(self,field_name,multi=False,condition=None,is_choice=False,text_func_name=None,val_func_name=None):
- """
- :param field_name: 字段
- :param multi: 是否多选
- :param condition: 显示数据的筛选条件
- :param is_choice: 是否是choice
- :param text_func_name: 在Model中定义函数,显示文本名称,默认使用str(对象)
- :param val_func_name: 在Model中定义函数,页面生成的a标签中对应的值的函数. 默认使用 对象.pk
- """
- self.field_name = field_name
- self.multi = multi
- self.is_choice = is_choice
- self.condition = condition
- self.text_func_name = text_func_name
- self.val_func_name = val_func_name
- def get_queryset(self,_field):
- if self.condition:
- return _field.rel.to.objects.filter(**self.condition)
- return _field.rel.to.objects.all()
- def get_choices(self,_field):
- return _field.choices
- class FilterRow(object):
- def __init__(self,option, data, request):
- self.data = data
- self.option = option # option: 要配置的对象 v1.FilterOption('depart',text_func_name=None,val_func_name=None)
- self.request = request
- def __iter__(self):
- params = copy.deepcopy(self.request.GET)
- params._mutable = True
- current_id = params.get(self.option.field_name) # 3
- current_id_list = params.getlist(self.option.field_name) # [1,2,3]
- if self.option.field_name in params:
- # del params[self.option.field_name]
- origin_list = params.pop(self.option.field_name)
- url = "{0}?{1}".format(self.request.path_info, params.urlencode())
- yield mark_safe('<a href="{0}">全部</a>'.format(url))
- params.setlist(self.option.field_name,origin_list)
- else:
- url = "{0}?{1}".format(self.request.path_info, params.urlencode())
- yield mark_safe('<a class="active" href="{0}">全部</a>'.format(url))
- # ( (1,男),(2,女) )
- for val in self.data:
- print('val---',val)
- if self.option.is_choice:
- pk,text = str(val[0]),val[1]
- else:
- # 如果你设置了这个函数就走你设置的函数,否则 str(val) str(val.pk)
- text = self.option.text_func_name(val) if self.option.text_func_name else str(val)
- pk = str(self.option.val_func_name(val)) if self.option.val_func_name else str(val.pk)
- # pk = str(self.option.val_func_name(val)) if self.option.val_func_name else str(val.pk)
- # pk,text = str(val.pk), str(val)
- # 当前URL?option.field_name
- # 当前URL?gender=pk
- # self.request.path_info # http://127.0.0.1:8005/arya/crm/customer/?gender=1&id=2
- # self.request.GET['gender'] = 1 # &id=2gender=1
- if not self.option.multi:
- # 单选
- params[self.option.field_name] = pk
- url = "{0}?{1}".format(self.request.path_info,params.urlencode())
- if current_id == pk:
- yield mark_safe("<a class='active' href='{0}'>{1}</a>".format(url,text))
- else:
- yield mark_safe("<a href='{0}'>{1}</a>".format(url, text))
- else:
- # 多选 current_id_list = ["1","2"]
- _params = copy.deepcopy(params)
- id_list = _params.getlist(self.option.field_name)
- if pk in current_id_list:
- id_list.remove(pk)
- _params.setlist(self.option.field_name, id_list)
- url = "{0}?{1}".format(self.request.path_info, _params.urlencode())
- yield mark_safe("<a class='active' href='{0}'>{1}</a>".format(url, text))
- else:
- id_list.append(pk)
- # params中被重新赋值
- _params.setlist(self.option.field_name,id_list)
- # 创建URL
- url = "{0}?{1}".format(self.request.path_info, _params.urlencode())
- yield mark_safe("<a href='{0}'>{1}</a>".format(url, text))
组合搜索相关
- 二:单例模式
第一种:文件导入
第二种:
自定义类方法(有代价,告知所有人,以后实例化时,不要再 类(),使用 类.instance() )
代码:
- class Foo(object):
- _instance = None
- def __init__(self, name):
- self.name = name
- @classmethod
- def instance(cls, *args, **kwargs):
- if not Foo._instance:
- obj = Foo(*args, **kwargs)
- Foo._instance = obj
- return Foo._instance
- obj1 = Foo.instance('ff')
- obj2 = Foo.instance('ff')
- print(id(obj1), id(obj2))
单例
什么时候用单例模式?
- 我们希望当程序运行起来,只需要创建一份时:例如 site=StarkSite()
- 全局变量在这也可以用(全局变量+类)
- 单例模式
- 使用(在哪里用到过程序运行只需要一份?):
- stark注册时—文件导入 stark组件
- redis连接(crm自动分配订单)
- 数据库连接 + 数据库连接池
三:销售中的公共资源:Q查询,3天 15天
- def public_view(self,request):
- """
- 公共客户资源, 未报名 & (15天未接单 or 三天未跟进)
- """
- current_user_id = 9
- # 当前日期
- current_date = datetime.datetime.now().date()
- # 最后接单时间
- no_deal = current_date - datetime.timedelta(days=15)
- # 最后跟进日期
- no_follow_date = current_date - datetime.timedelta(days=3)
- """公共客户"""
- # 方法一:
- # customer_list = models.Customer.objects.filter(Q(recv_date__lt=no_deal)|Q(last_consult_date__lt=no_follow),status=2)
- # customer_list = models.Customer.objects.filter(Q(recv_date__lt=no_deal)|Q(last_consult_date__lt=no_follow_date),status=2)
- # print('9999999999',customer_list)
- # 方法二:
- con = Q()
- q1 = Q(status=2)
- q2 = Q()
- q2.connector = 'OR'
- q2.children.append(('recv_date__lt', no_deal))
- q2.children.append(('last_consult_date__lt', no_follow_date))
- con.add(q1,'AND')
- con.add(q2,'AND')
- customer_list = models.Customer.objects.filter(con)
- return render(request, 'public_view.html', {'customer_list':customer_list, "current_user_id":current_user_id})
public_view
四:使用yield实现
- 生成器函数,对数据进行加工处理
- FilterRow里面,yield生成前端组合搜索中的每一行搜索条件。
- __iter__和yield配合
五:获取Model类中的字段对应的对象
- 1. def(request):
- 2. a=models.UserInfo._meta.get_field('name')
- 3. #app01.UserInfo.name
- 4. b=models.UserInfo._meta.fields
- 5. #(<django.db.models.fields.AutoField:id>,
- 6. #<django.db.models.fields.CharField:name>,
- 7. #<django.db.models.fields.CharField:username>,
- 8. #<django.db.models.fields.CharField:password>,
- 9. #<django.db.models.fields.EmailField:email>,
- 10. #<django.db.models.fields.related.ForeignKey:depart>)
- 1. c=models.UserInfo._meta._get_fields()
- 2. #(<ManyToOneRel:app01.classlist>,
- 3. #<ManyToManyRel:app01.classlist>,
- 4. #<ManyToOneRel:app01.customer>,
- 5. #<ManyToOneRel:app01.customerdistribution>,
- 6. #<ManyToOneRel:app01.salerank>,
- 7. #<ManyToOneRel:app01.consultrecord>,
- 8. #<ManyToOneRel:app01.paymentrecord>,
- 9. #<ManyToOneRel:app01.courserecord>,
- 10. #<django.db.models.fields.AutoField:id>,
- 11. #<django.db.models.fields.CharField:name>,
- 12. #<django.db.models.fields.CharField:username>,
- 13. #<django.db.models.fields.CharField:password>,
- 14. #<django.db.models.fields.EmailField:email>,
- 15. #<django.db.models.fields.related.ForeignKey:depart>)
- 1. d=models.UserInfo._meta.many_to_many#()
1
- # 根据类名获取响应字段
- model.UserInfo
- model.UserInfo._meta.app_label#获取当前app的名称
- model.UserInfo._meta.model_name#获取当前类名小写
- model.UserInfo._meta.get_field('username')#获取字段
- model.UserInfo._meta.get_field('username').verbose_name#获取verbose_name
- model.UserInfo._meta.get_field('外键或多对多字段').rel.to #得到关联的model类
- - models.UserInfo._meta.get_field('name') # 根据字段名称,获取字段对象
- - models.UserInfo._meta.fields # 获取类中所有的字段
- - models.UserInfo._meta._get_fields() # 获取类中所有的字段(包含反向关联的字段)
- - models.UserInfo._meta.many_to_many # 获取m2m字段
2
- # 获取当前类的对象,所反向关联的字段
- related_fileds=obj._meta.related_objects #得到当前对象的反向关联的所有字段
- for related_field in fileds:
- _model_name=related_field.field.model._meta.model_name#获取当前关联字段所属的类名
- _related_name=related_field.related_name#获取当前字段中的_related_name(反向查找的别名)
- _field_name=related_field.field_name#获取当前字段跟其他表所关联的字段(to_field='')
- _limit_choices_to=related_obj.limit_choices_to
3
六:模糊搜索功能
知识:
- contains
- Q查询
- 示例:
- Q
- con = Q()
- q1 = Q()
- q1.connector = 'or'
- q1.children.append( ('name','ff1') )
- q1.children.append( ('name','ff2') )
- q2 = Q()
- q2.children.append( ('age__gt',18))
- q2.children.append( ('id__gt',18))
- con.add(q1,'OR')
- con.add(q2,'OR')
- # (name='ff' or name=='ff2') or (age>18 and id > 18)
- queryset = self.model_class.objects.filter(con)
Q
代码:
- show_search_form = False # 是否显示搜索框
- def get_show_search_form(self):
- return self.show_search_form
- search_fields = [] # 搜索的字段
- def get_search_fields(self):
- result = []
- if self.search_fields:
- result.extend(self.search_fields)
- return result
- def get_search_condition(self):
- key_word = self.request.GET.get(self.search_key)
- search_fields = self.get_search_fields()
- condition = Q()
- condition.connector = 'or'
- if key_word and self.get_show_search_form():
- for field_name in search_fields:
- condition.children.append((field_name, key_word))
- return condition
后台相关
- # 显示搜索并支持模糊搜索
- show_search_form = True
- search_fields = ['name__contains']
配置代码
- {% if cl.show_search_form %}
- <div class="form-group pull-right">
- <form method="get">
- <input name="{{ cl.config.search_key }}" value="{{ cl.search_form_val }}" class="form-control"
- placeholder="请输入搜索条件" type="text" style="display:inline-block;width: 200px;"/>
- <button class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
- </form>
- </div>
- {% endif %}
前端代码
七:Type创建类
看图:
内置的type()函数带有三个参数,
- Type(name,bases,dict)
- 它会返回一个新的type对象,类似于class语句的动态形式.
- 参数 :
- name 参数指的是你的类名.赋给新对象__name__属性
- bases 一个tuple,指定新类型的所有基类,赋给新对象__bases__属性
- 父类, 因为支持多重继承,所以用tuple
- dict 字典类型,作为新类的命名空间,赋给新对象__dict__属性
- 类的初始化元素
- dict 字典类型,作为新类的命名空间,赋给新对象__dict__属性
三个参数: 第一个参数为类名,第二个参数是要继承的类,第三个参数就是字段了。
本项目中的应用:
在录入成绩的时候,动态创建类。根据自定义字段,获取到自己想要的数据。
八:自动派单
- 原来在内存中实现,问题:重启和多进程时,都有问题。
- redis
- 状态
- 原来数据(权重表 权重和个数)
- pop数据
九:reverse反向生成URL
根据url中name字段。使用reverse来反向生成url。如果有namespace字段,则需要使用 :号来分隔爱。 前面是namespace,后面是name。
十:模版继承
母版: 在页面最上方加上{% block content %}...{% endblock %}
基板:如何继承?
页面最上方:{% extend '模板路径' %}
页面内容中:{% block content %}...{% endblock %}
懂了没? 不懂的话... 看图:
十一:ready方法定制起始文件
- 文件导入实现单例模式
- from django.apps import AppConfig
- class StarkConfig(AppConfig):
- name = 'stark'
- def ready(self):
- from django.utils.module_loading import autodiscover_modules
- autodiscover_modules('stark')
stark/apps
十三:inclusion_tag
- 用于popup生成,之前的代码里有。
- 友情链接:popUp
- 我们通过对一个 Library 对象使用 inclusion_tag() 方法来创建并注册这个包含标签。
- 将当前所装饰的函数得到的值,传入到inclusion_tag()的html中,如果有模板需要用到这个html模板(将此作为基板),则需要在当前模板中
- {% inclusion_tag所修饰的函数名 参数一 参数二....%}
- 看图吧还是。 那个load change_form是一个py文件,里面放的就是图一的东西。
十四:中间件的使用
- 用户登录来一个
- 登陆后用户权限来一个
15. importlib + getattr
16. FilterOption,lambda表达式
17. QueryDict
- 原条件的保留
- filter
18. ModelForm
19. 面向对象的 @property @classmethod
20. mark_safe
21. 抽象方法抽象类+raise Im...
22. 组件中的装饰器,实现self.request = request
23. 自执行函数
(function(arg){
})('sf')
24. URL的钩子函数
def extra_url(self):
pass
25. 多继承
26. 批量导入,xlrd
27. redis连接池
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方法
?????????????????????????
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. 深浅拷贝(http://blog.csdn.net/jerry_1126/article/details/41852591)
- 深浅拷贝都是对源对象的复制,占用不同的内存空间
- 如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
- 如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
- 序列对象的切片其实是浅拷贝,即只拷贝顶级的对象
CRM知识点汇总(未完💩💩💩💩💩)的更多相关文章
- ASP.NET MVC 系列随笔汇总[未完待续……]
ASP.NET MVC 系列随笔汇总[未完待续……] 为了方便大家浏览所以整理一下,有的系列篇幅中不是很全面以后会慢慢的补全的. 学前篇之: ASP.NET MVC学前篇之扩展方法.链式编程 ASP. ...
- CareerCup All in One 题目汇总 (未完待续...)
Chapter 1. Arrays and Strings 1.1 Unique Characters of a String 1.2 Reverse String 1.3 Permutation S ...
- 清华大学OS操作系统实验lab1练习知识点汇总
lab1知识点汇总 还是有很多问题,但是我觉得我需要在查看更多资料后回来再理解,学这个也学了一周了,看了大量的资料...还是它们自己的80386手册和lab的指导手册觉得最准确,现在我就把这部分知识做 ...
- ECMAScript版本知识点汇总
ECMAScript版本知识点汇总 ES5 btoa.atob 对参数进行base64格式编码.解码 /** * btoa() * base64编码 * @param {string} str * @ ...
- 前端开发 JavaScript 干货知识点汇总
很多初学的朋友经常问我,前端JavaScript都需要学习哪些东西呀?哪些是JavaScript的重点知识啊? 其实做前端开发工程师,所有的知识点都是我们学习必备的东西,只有扎实的技术基础才是高薪的关 ...
- javascript有用小功能总结(未完待续)
1)javascript让页面标题滚动效果 代码如下: <title>您好,欢迎访问我的博客</title> <script type="text/javasc ...
- 关于DOM的一些总结(未完待续......)
DOM 实例1:购物车实例(数量,小计和总计的变化) 这里主要是如何获取页面元素的节点: document.getElementById("...") cocument.query ...
- 我的SQL总结---未完待续
我的SQL总结---未完待续 版权声明:本文为博主原创文章,未经博主允许不得转载. 总结: 主要的SQL 语句: 数据操作(select, insert, delete, update) 访问控制(g ...
- virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续)
virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续) 第一次接触到 linux,不知道linux的确很强大,然后用virtualbox ...
随机推荐
- arcgis jsapi接口入门系列(0):总览
开发环境: arcgis jsapi版本4.9 由于我们这套代码是基于vue,webpack开发的,会有少数vue代码,但总体不影响 里面还有些我们公司的js库和html css,给出的代码不能百分百 ...
- deb软件安装
deb是debian linux的安装格式,跟red hat的rpm非常相似,最基本的安装命令是:dpkg -i file.deb dpkg 是Debian Package的简写,是为Debian 专 ...
- 剑指offer课外两道习题解法
1.定义一个函数,删除字符串中所有重复出现的字符,例如输入“google”,删除重复的字符之后的结果为“gole”. 解题思路:像这种求字符串的重复字符,并且去掉重复字符,我们一般可以用哈希 ...
- 小目标 | Power BI新人快速上手手册
· 适用人群:数据分析专业人士,在数据分析方向需求发展人士 · 应用场景:数据汇报.数据可视化展现.数据建模分析 · 掌握难度:★★★★☆ 本期讲师 『PowerPivot工坊』公众号提供Power ...
- MySQL查询优化方法总结
1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...
- Jquery 事件 DOM操作
常规事件: 把JS的事件 on去掉即可 例如:js document.getElementById("id").onclinck=function(){} Jquery ...
- github的pull Request使用
场景: teamA要一起做一个项目,选择用github管理自己的代码仓库,这时userA在github上新建了一个远程仓库,其他人需要通过pull request来实现提交.那么,问题来了,pull ...
- pycharm使用秘籍 和 pip命令
python使用requirements.txt批量安装包 requirements.txt文件格式: requests==1.2.0 Flask==0.10.1 等等一系列包 cd 到requir ...
- DDOS介绍
DDOS: Data Domain Operating System(DD OS),即数据域操作系统----管理EMC的数据域拷贝存储系统(powers EMC Data Domain dedupli ...
- UVA 1613 K-Graph Oddity K度图着色 (构造)
题意:在一个n个点的无向连通图中,n是奇数,k是使得所有点的度数不超过k的最小奇数,询问一种染色方案,使得相邻点的颜色不同. 题解:一个点和周围的点的颜色数加起来最大为它的度数+1:如果最大度数是偶数 ...