Django13 /緩存、信號、django的讀寫分離

Django13 /緩存、信號、django的讀寫分離

[TOC]html

1. 緩存

  • 緩存簡述:python

    緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行views中的操做,而是直接從內存或者memcache中以前緩存的內容拿到,並返回。
  • Django中緩存的方式mysql

    開發調試
    內存
    文件
    數據庫
    Memcache緩存(python-memcached模塊)
    Memcache緩存(pylibmc模塊)
  • 各類方式的配置redis

    一、將緩存內容保存在內存的變量中(django的默認配置)sql

    # 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)
    		},
    } }

    二、將緩存內容保存在文件中數據庫

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

    三、將緩存內容保存在數據庫中django

    # 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指令就可使用。

    四、將緩存內容保存在redis中緩存

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

    一、單獨視圖使用緩存框架

    # 方式一:語法糖裝飾器
    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)),
    ]

    二、模板局部使用緩存,就不須要在視圖中設置緩存了

    <!-- 用法以下: -->
    
    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>

    三、全局使用緩存

    # 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          # 建立數據庫鏈接時,自動觸發
  • 信號的使用

    一、註冊指定信號,當程序執行相應操做時,自動觸發註冊函數

    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文件中註冊信號

    二、在視圖函數中,作相應的操做就會觸發相應的函數

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

    一、定義信號:在某py文件或者項目或者應用的__init__.py文件中定義信號。

    import django.dispatch
    pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
    
    # 注意:toppings和size這兩個參數名稱隨便,不是固定的,可是使用的時候關鍵字傳參的時候,要和這兩個參數的名稱對應好,能夠經過設置參數來進行一個判斷處理等操做

    二、註冊信號:在__init__.py中註冊信號

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

    三、觸發信號

    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使用讀寫分離

    一、手動實現,在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})

    二、自動實現,進行相關配置

    # 在應用文件夾中建立一個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})
  • 一主多從的時候,也就是從多個數據庫中讀取的時候:

    一、多個數據庫進行隨機讀取的

    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'

    二、根據不一樣的應用來選擇不一樣的庫進行讀取

    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):
相關文章
相關標籤/搜索