Django13 /缓存、信号、django的读写分离

1. 缓存

  • 缓存简述:

    缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行views中的操作,而是直接从内存或者memcache中之前缓存的内容拿到,并返回。
  • Django中缓存的方式

    开发调试
    内存
    文件
    数据库
    Memcache缓存(python-memcached模块)
    Memcache缓存(pylibmc模块)
  • 各种方式的配置

    1、将缓存内容保存在内存的变量中(django的默认配置)

    # settings配置文件中写如下配置:
    
    CACHES = {
    'default': {
    'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    'LOCATION': 'unique-snowflake', #这是一个唯一标示,写啥都行
    'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
    'OPTIONS':{
    'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
    'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
    },
    } }

    2、将缓存内容保存在文件中

    # settings配置文件中写如下配置:
    
    CACHES = {
    'default': {
    'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
    'LOCATION': '/var/tmp/django_cache', #缓存文件存放路径
    }
    }

    3、将缓存内容保存在数据库中

    # settings配置文件中写如下配置:
    
    # 方式一:执行创建表命令生成数据库表
    CACHES = {
    'default': {
    'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
    'LOCATION': 'my_cache_table', # 数据库表
    }
    } # 注:执行创建表命令 python manage.py createcachetable,数据库中会自动生成名字为my_cache_table的表作为缓存表 # 方式二:自己创建存放缓存内容的数据库表
    from django.db import models class CacheTalbe(models.Model):
    cache_key = models.CharField(max_length=2000)
    value = models.CharField(max_length=2000,null=True)
    expires = models.DateTimeField(null=True) # 注:如果自己手动创建这个缓存表的时候,数据库表的三个字段是必须要有的:看下面的表,并且不需要制定上面的createcachetable指令就可以使用。

    4、将缓存内容保存在redis中

    # settings配置文件中写如下配置:
    
    CACHES = {
    "default": {
    "BACKEND": "django_redis.cache.RedisCache",
    "LOCATION": "redis://127.0.0.1:6379",
    "OPTIONS": {
    "CLIENT_CLASS": "django_redis.client.DefaultClient",
    }
    }
    }
  • 缓存的使用

    1、单独视图使用缓存

    # 方式一:语法糖装饰器
    from django.views.decorators.cache import cache_page
    import time
    @cache_page(5) # 设置5秒后缓存到期
    def my_view(request):
    tm = time.time() # 用时间戳模拟测试
      return render(request,'index.html',{'tm':tm }) # 刷新页面,5s内会一直使用缓存 # 方式二:装饰器原始用法
    from django.views.decorators.cache import cache_page
    urlpatterns = [
    url(r'^foo/([0-9]{1,2})/$', cache_page(5)(my_view)),
    ]

    2、模板局部使用缓存,就不需要在视图中设置缓存了

    <!-- 用法如下: -->
    
    a. 引入TemplateTag
    {% load cache %} b. 使用缓存
    {% cache 5 key %} <!-- key就是存储缓存时的键 -->
    缓存的内容
    {% endcache %}
    <!-- 示例代码如下: -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body> <h1>测试模板局部使用缓存</h1>
    <h2>{{ tm }}</h2> {% load cache %}
    {% cache 5 'key' %}
    <h2>{{ tm }}</h2>
    {% endcache %} </body>
    </html>

    3、全局使用缓存

    # settings配置文件进行如下配置:
    
    MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware', # 中间件第一个
    # 其他中间件...
    'django.middleware.cache.FetchFromCacheMiddleware', # 中间件最后一个
    ] CACHE_MIDDLEWARE_ALIAS = "" # 用于存储的缓存别名。
    CACHE_MIDDLEWARE_SECONDS = "" # 缓存的过期秒数
    CACHE_MIDDLEWARE_KEY_PREFIX = "" # 如果使用同一django安装跨多个站点共享缓存,请将其设置为站点名称或此django实例唯一的其他字符串,以防止密钥冲突。如果不在乎,就用空字符串。 # 注意:使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
  • 总结:

    • 缓存是以加密的形式进行保存的
    • 对实时性数据要求很高的,不要做缓存

2. 信号

  • 信号简述:

    Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。
  • Django内置的信号

    pre_init                    # django的model执行其构造方法前,自动触发
    post_init # django的model执行其构造方法后,自动触发
    pre_save # django的model对象保存前,自动触发,新增或者更新都是保存
    post_save # django的model对象保存后,自动触发
    pre_delete # django的model对象删除前,自动触发
    post_delete # django的model对象删除后,自动触发
    m2m_changed # django的model中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
    class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
    Management signals
    pre_migrate # 执行migrate命令前,自动触发
    post_migrate # 执行migrate命令后,自动触发
    Request/response signals
    request_started # 请求到来前,自动触发
    request_finished # 请求结束后,自动触发
    got_request_exception # 请求异常后,自动触发
    Test signals
    setting_changed # 使用test测试修改配置文件时,自动触发
    template_rendered # 使用test测试渲染模板时,自动触发
    Database Wrappers
    connection_created # 创建数据库连接时,自动触发
  • 信号的使用

    1、注册指定信号,当程序执行相应操作时,自动触发注册函数

    from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed
    from django.test.signals import template_rendered from django.db.backends.signals import connection_created def callback(sender, **kwargs): # sender表示信号触发者
    print("已经触发信号了")
    print(sender,kwargs) post_save.connect(callback) # 表示model对象保存后,会自动触发callback函数 # 在视图中或者项目或者应用的__init__.py文件中注册信号

    2、在视图函数中,做相应的操作就会触发相应的函数

    from app01 import models
    
    def func(sender,**kwargs):
    models.Book.objects.create(title='python')
    return HttpReponse('ok')
  • 自定义信号

    1、定义信号:在某py文件或者项目或者应用的__init__.py文件中定义信号。

    import django.dispatch
    pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) # 注意:toppings和size这两个参数名称随便,不是固定的,但是使用的时候关键字传参的时候,要和这两个参数的名称对应好,可以通过设置参数来进行一个判断处理等操作

    2、注册信号:在__init__.py中注册信号

    def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs) pizza_done.connect(callback)

    3、触发信号

    from 路径 import pizza_done
    
    pizza_done.send(sender='seven',toppings=123, size=456)

3. django的读写分离

  • django的读写分离简述:

    django做的其实是在数据库已经做好读写分离的情况下,怎么使用
  • 首先配置多个数据库,在settings配置文件中配置以下内容:

    DATABASES = {
    'default': { # 默认数据库,配置多个mysql数据也是ok的,混用数据库也是ok的
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'db2': { # 配置的第二个数据库,注意数据库名字不能相同
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),
    }
    }
  • 执行数据库同步指令,将默认数据库的表结构生成到db2这个数据库中

    python migrate --database db2(库名)
  • django使用读写分离

    1、手动实现,在views.py文件中进行操作时指定数据库

    def dbtest(request):
    data = []
    # 向db2数据库中写入数据
    models.Class.objects.using('db2').create(name='xx') # 从默认数据库中读取数据
    data = models.Class.objects.using('default').all()
    # 更新时
    for i in data:
    i.name = '张三'
    i.save(using='default') # 更新时指定数据库
    return render(request,'dbtest.html',{'data':data})

    2、自动实现,进行相关配置

    # 在应用文件夹中创建一个py文件,比如叫做router.py文件,写如下内容:
    
    class Router:
    def db_for_read(self,model,**kwargs):
    return 'default' def db_for_write(self,model,**kwargs):
    return 'db2'
    # settings配置文件做如下配置
    
    DATABASE_ROUTERS = ['app01.router.Router',]
    # []中写上面Router类的路径
    # 在views.py中,进行读写操作时,会自动操作不同的数据库
    
    def dbtest(request):
    data = []
    # 向db2数据库中写入数据
    models.Class.objects.create(name='李四') # 从默认数据库中读取数据
    data = models.Class.objects.all() return render(request,'dbtest.html',{'data':data})
  • 一主多从的时候,也就是从多个数据库中读取的时候:

    1、多个数据库进行随机读取的

    import random
    class Router:
    def db_for_read(self,model,**kwargs):
    print(model._meta.app_label)
    return random.choice(['db1','db2','db3']) # 多个库读的时候,可以简单的写个随机选择 def db_for_write(self,model,**kwargs):
    return 'db2'

    2、根据不同的应用来选择不同的库进行读取

    class Router:
    def db_for_read(self,model,**kwargs):
    print(model)
    print(dir(model)) # 其中有个_meta属性很有用
    app_name = model._meta.app_label # 获取当前model对象所在的应用名称
         m = model._meta.model_name # 获取当前操作的model对象的表名,也可以根据表名来进行多数据库读的分配 # 可以根据应用选择不用的库来进行读取
    if app_name == 'app01':
    return 'db1'
    elif app_name == 'app02':
    return 'db2'
    return 'default' def db_for_write(self,model,**kwargs):

最新文章

  1. java日历显示年份、月份
  2. 第3章 jQuery的DOM操作
  3. HTML5语义化标签
  4. 控制CPU占用率曲线
  5. sqlserver 理解数据集
  6. 初探swift语言的学习笔记七(swift 的关健词)
  7. 四、WCF的配置文件
  8. Iterator、for..of,for...in和自定义遍历器**
  9. 有关struts中DispatchAction的用法小结
  10. 嵌入式linux网络配置
  11. Nhibernate学习教程(1)-- 开篇有益
  12. ext4 关闭延迟分配
  13. string find()函数
  14. CAN总线要点
  15. jquery easyui教程[申明:来源于网络]
  16. jsp/servlet学习三之会话管理初解
  17. hashlib
  18. jzoj4229
  19. Docker 部署学习
  20. 如何理解springaop

热门文章

  1. CollectionView的cell长按事件实现
  2. acm对拍程序 以及sublime text3的文件自动更新插件auto refresh
  3. loadrunner常见问题及解决办法
  4. Dubbo——服务发布原理
  5. cocos2dx 启用cjson
  6. android KeyEvent事件机制
  7. android handle详解
  8. 尚学堂 216 java中的字节码操作
  9. Pytorch入门——手把手带你配置云服务器环境
  10. EnvironmentPostProcessor