CRM知识点汇总(未完💩💩💩💩💩)

一:项目中每个类的作用

    • StarkSite
      • 对照admin中的AdminSite相当于一个容器,用来存放类与类之间的关系。
        • 先实例化对象,然后执行该对象的register方法。将注册类添加到_register = {}中。
        • {

          models.UserInfo:StarkConfig(models.UserInfo,self),

          models.Role:StarkConfig(models.Role,self)

          }

  • StarkConfig
    • 用来处理增删改查的基类。
    • 以后每个自定义的类都需要继承的基类。
    • 页面上有请求过来时,先到该类下的视图函数。
      • Add_view下,要区分是否是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; 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__属性
      •   类的初始化元素

三个参数: 第一个参数为类名,第二个参数是要继承的类,第三个参数就是字段了。

本项目中的应用:

   在录入成绩的时候,动态创建类。根据自定义字段,获取到自己想要的数据。

八:自动派单

- 原来在内存中实现,问题:重启和多进程时,都有问题。

- 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. FilterOptionlambda表达式

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)

  1. 深浅拷贝都是对源对象的复制,占用不同的内存空间
  2. 如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
  3. 如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝
  4. 序列对象的切片其实是浅拷贝,即只拷贝顶级的对象

原文地址:https://www.cnblogs.com/Wormhole-f/p/8231454.html