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 ...
随机推荐
- Kendo DataSource 概述
Kendo DataSource 概述 Kendo 的数据源支持本地数据源( JavaScript 对象数组),或者远程数据源(XML, JSON, JSONP),支持 CRUD 操作(创建,读取,更 ...
- Log Structured Merge Trees(LSM) 算法
十年前,谷歌发表了 “BigTable” 的论文,论文中很多很酷的方面之一就是它所使用的文件组织方式,这个方法更一般的名字叫 Log Structured-Merge Tree. LSM是当前被用在许 ...
- specrate 与specspeed 的区别
What is the difference between a "rate" and a "speed" metric?There are several d ...
- 对fgets末尾'\0'的处理
之所以要对fgets自动添加的字符进行处理的原因之一是:当你想比较输入的字符时,你会发现输入的字符和源码用来进行对比的字符一模一样,但是使用strcmp比较时就是不一样,原因就是fgets对输入字符添 ...
- Docker搭建
环境基于CentOS64位,内核最好3.10. 1.下载安装 docker dockersudo yum install docker-io (假如内核版本太低的话,会在下载安装Docker ...
- 一点对Promise的理解与总结
全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/10959411.html,多谢,=.=~ axios用多了就开始疑惑它里面到底是个啥,虽然总被告知 ...
- 洛谷 P2383 狗哥玩木棒
题目背景 狗哥又趁着语文课干些无聊的事了... 题目描述 现给出一些木棒长度,那么狗哥能否用给出的木棒(木棒全用完)组成一个正方形呢? 输入输出格式 输入格式: 输入文件中的第一行是一个整数n表示测试 ...
- xwork-conversion.properties 目前没有解决方案
它没法变成.xml 这意味着项目里就只能这样
- jquery的uploadify插件实现的批量上传V3.2.1版
你需要如下配置(包括引入文件)HTML: <html xmlns="http://www.w3.org/1999/xhtml"> <head runat=&quo ...
- tpcc-mysql 实践
一.TPCC 介绍 TPC:全称Transaction Processing Performance Council (事务处理性能委员会),是一家非盈利性组织,该组织制定各种商业应用的基准测试规范, ...