Django進階之旅

1.django-debug-toolbar

  • 介紹css

  • django-debug-toolbar 是一組可配置的面板,可顯示有關當前請求/響應的各類調試信息,並在單擊時顯示有關面板內容的更多詳細信息。返回HttpResponse會失效html

  • 安裝:python

    pip3 install django-debug-toolbar
  • settingsjquery

#將 debug_toolbar 添加到 INSTALL_APPS 中
INSTALLED_APPS = [
    'debug_toolbar',
]
#若是是本機調試,還在將127.0.0.1加入 INTERNAL_IPS
INTERNAL_IPS = ("127.0.0.1",)
#在中間件中加入DebugToolbarMiddleware
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
#配置jQuery的URL
    #django-debug-toolbar 默認使用的是Google的地址,默認配置以下:
    JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'
    #國內用不了的話能夠在settings.py中配置一下,例如(我這裏特地選用了和原做者相同版本的jQuery):
    DEBUG_TOOLBAR_CONFIG = {
    "JQUERY_URL": '//cdn.bootcss.com/jquery/2.2.4/jquery.min.js',
}
  • urls.py中
from django.conf import settings

if settings.DEBUG:#
    import debug_toolbar

    urlpatterns = [
                      url(r'^__debug__/', include(debug_toolbar.urls)),
                  ] + urlpatterns

2.緩存

  • 因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行view中的操做,而是直接從內存或者memcache中以前緩存的內容拿到,並返回。ajax

  • 開發調試--->起到佔位做用,自己不具有緩存。等上線以後更改配置便可使用redis

    不作任何緩存。咦?不作任何緩存?沒聽錯吧,那幹嗎要用它呢?
    
    由於是開發調試模式,在本地進行調試,調試過程當中,全部的相關緩存配置都須要加上,可是本身調試時候不須要加配置(效果半小時失效,不能幹等半個小時看效果吧),要實時看結果。先起到佔位做用,等到上線,再改配置就可使用了。
  • 內存sql

  • 文件數據庫

  • 數據庫django

  • Memcache緩存(python-memcached模式)後端

  • Memcache緩存(pylibmc模塊)

  • www.cnblogs.com/maple-shaw/articles/7563029.html

2.1 基於內存進行緩存的配置

1.settings.py

# 此緩存將內容保存至內存的變量中
# 配置:
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.給視圖加緩存
from django.views.decorators.cache import cache_page
@cache_page(5)#裝飾器cache_timeout=5表示緩存超時時間5秒
def student_list(request):
    students = models.Student.objects.all()
    print("打印表明沒緩存")
    return render(request,'stu.html',{"students":students})
#5秒內除了第一次,屢次訪問是沒有打印結果,表明不走緩存

2.2 基於文件進行緩存的配置

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': 'G:\homework\day複習篇\day121Django\緩存\cache',
        'TIMEOUT': 300,         # 緩存超時時間(默認300,None表示永不過時,0表示當即過時)
        'OPTIONS':{
            'MAX_ENTRIES': 300,  # 最大緩存個數(默認300)
            'CULL_FREQUENCY': 3, # 緩存到達最大個數以後,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認3)
        },
    }
}


#只是更改了'BACKEND' :'django.core.cache.backends.filebased.FileBasedCache'
#'LOCATION' 文件存儲位置。生成 .djcache後綴文件

2.3基於數據庫進行緩存的配置

1.
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table',
        'TIMEOUT': 300,         # 緩存超時時間(默認300,None表示永不過時,0表示當即過時)
        'OPTIONS':{
            'MAX_ENTRIES': 300,  # 最大緩存個數(默認300)
            'CULL_FREQUENCY': 3, # 緩存到達最大個數以後,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認3)
        },
    }
}

2.Terminal執行命令:
    python3 manage.py createcachetable
    生成表:表字段cache_key,value,expires

2.4基於Memcache進行緩存的配置

#ip端口訪問
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}
#創建socket訪問
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': 'unix:/tmp/memcached.sock',
    }
}   
#多個緩存ip和端口,相似分佈式
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    }
}

2.5全站使用緩存

  • 使用中間件,通過一系列的認證等操做,若是內容在緩存中存在,則使用FetchFromCacheMiddleware獲取內容並返回給用戶,當返回給用戶以前,判斷緩存中是否已經存在,若是不存在則UpdateCacheMiddleware會將緩存保存至緩存,從而實現全站緩存
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',#最上面
# 其餘中間件...
'django.middleware.cache.FetchFromCacheMiddleware',#最下面
]
#只是添加2箇中間件UpdateCacheMiddleware做用是更新緩存,FetchFromCacheMiddleware從緩存中獲取數據

2.6局部模板使用緩存

  • 指的是頁面返回數據,由於頁面有些數據要實時看,有些不須要實時更新的。給不常常發生變化的加上緩存。
  • views.py
import time
from django.shortcuts import render
from app01 import models
def student_list(request):
    students = models.Student.objects.all()
    print("打印表明沒緩存")
    now = time.time()
    return render(request,'stu.html',{"students":students,"now":now})#往模版傳入時間
  • 模版
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    {% for student in students %}
        <li>{{ student.name }}</li>
    {% endfor %}
</ul>
    {# 實時更新 時間#}
    {{ now }}
<br>
{# 導入緩存#}
{% load cache %}
{# 設置緩存 5秒 更新一次,必須還有設置一個key #}
{% cache 5 'keys'%}
緩存{{ now }}{# 內部代碼5秒更新一次 #}
{% endcache %}
</body>
</html>

2.7 django-redis配置

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        #1爲redis 的 1號庫
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}
  • 做爲 session backend 使用配置

    • Django 默承認以使用任何 cache backend 做爲 session backend, 將 django-redis 做爲 session 儲存後端不用安裝任何額外的 backend
    SESSION_ENGINE = "django.contrib.sessions.backends.cache"
    SESSION_CACHE_ALIAS = "default"

3.信號

  • Django中提供了「信號調度」,用於在框架執行操做時解耦。通俗來說,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者。
  • 應用:好比插入數據到數據庫,插入以前寫日誌,插入以後寫日誌。
Model signals
    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.信號用法一:

  • 對於Django內置的信號,僅需註冊指定信號,當程序執行相應操做時,自動觸發註冊函數,註冊信號,寫入與project同名的文件夾下的__init__.py文件中,也是換數據庫引擎的地方。這裏拿post_save舉例

    • __init__.py
    # post_save:django的model對象保存後,自動觸發
    from django.db.models.signals import post_save
    def callback(sender,**kwargs):
        print("執行post_save信號")
        print(sender,kwargs)
    
    post_save.connect(callback)#信號鏈接,並調用回調函數
    • views.py
    def student_list(request):
        students = models.Student.objects.all()
        print(students)
        models.Student.objects.create(name='xxoo')#建立一個對象,用於觸發信號
        return render(request,'stu.html',{"students":students})

2.信號用法二:

  • 經過裝飾器receiver,也能夠添加多個信號
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save)# django的model對象保存後,自動觸發
def callback(sender,**kwargs):
    print("執行post_save信號")
    print(sender,kwargs)

post_save.connect(callback)

@receiver(pre_save)# django的model對象保存前,自動觸發
def callback2(sender,**kwargs):
    print("執行pre_save信號")
    print(sender,kwargs)

pre_save.connect(callback2)

3.自定義信號:

  • 在一個py文件定義信號!sig.py
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])#toppings,size本身定義字段
  • __init__.py中註冊信號
from sig import pizza_done
def callback(sender, **kwargs):
    print("callback")
    print(sender, kwargs)


pizza_done.connect(callback)

#觸發後打印結果:
callback

seven {'signal': <django.dispatch.dispatcher.Signal object at 0x000001BCD6D82B38>, 'toppings': 123, 'size': 456}
  • 在視圖函數觸發信號因爲內置信號的觸發者已經集成到Django中,因此其會自動調用,而對於自定義信號則須要開發者在任意位置觸發

    from django.shortcuts import render
    from app01 import models
    
    from sig import pizza_done
    
    def student_list(request):
      students = models.Student.objects.all()
      pizza_done.send(sender='seven', toppings=123, size=456)#給sig中定義的字段傳值,發起信號者賦值
      return render(request,'stu.html',{"students":students})
觸發信號:單獨寫文件,若是在視圖函數寫函數,當代碼取消,不方便。若是單獨寫函數,雖然添加信號會繁瑣,但功能不須要取消時候,就方便許多。

4.orm性能相關

  • 儘可能不用對象進行查詢,多用values
  • select_related('關聯外鍵字段') 連表查詢 用於多對一,一對一
  • prefetch_related('關聯外鍵字段') 子表查詢 用於多對一,多對多

  • 只要返回某個字段。只是查某些字段 only('name')
  • 排除某些字段,defer("name")
  • QuerySet特性

1. 儘可能不查對象,會跨表或多語句查詢,用values直接取字段值,跨表一條語句,且結果爲字典

    查詢指定字段值時,儘可能不用對象,而使用values直接取值
    def index(request):
        ret = models.Student.objects.all()  #獲取全部對象
        for i in ret:
            print(i.name,i.classname)   #這裏要跨表查詢對象的外鍵關聯數據值時,orm會每個對象都發一次sql查詢,效率下降
        return render(request,'index.html',{'students':ret,})
    #核心問題時咱們經過對象點出來外鍵關聯屬性,咱們能夠不用all查詢對象,而是用values直接獲取到咱們要的屬性和值
    def index(request):
        ret = models.Student.objects.values('name','classname')  #獲取全部數據
        for i in ret:
            print(i[name],i[classname])   #這裏values獲得的是字典,字典取值便可,此時orm會只發一次sql作了一次連表查詢,效率高
        return render(request,'index.html',{'students':ret,})

2. 對象查詢時, 一對1、多對一獲取關聯對象時,使用select_related(‘外鍵字段’) 使多條語句sql合併爲一條鏈表查詢sql
   ret = models.Student.objects.all().select_related('classes')
   這條語句會在查詢對象時,經過使用外鍵,仍能連表查詢,效率提升

3. 對象查詢時,多對一多對多時使用prefetch_related(’外鍵‘),把多條sql合併使用子查詢,減小查詢次數
   ret = models.Student.objects.all().prefetch_related('classes')

4. 當對象查詢指定字段值時,在orm後添加.only(‘指定字段’),獲得的仍然是對象,與value不一樣的是value獲得的是字典
   ret = models.Student.objects.all().only('name')

5. 當對象查詢排除指定字段時,在orm後添加.defer(‘指定字段’),獲得的仍然是對象,與value不一樣的是value獲得的是字典
   ret = models.Student.objects.all().defer('name')
6. query_set特性
   只有在使用時纔會查詢數據庫,而不是遇到查詢語句就執行,好比html對象頁面渲染
相關文章
相關標籤/搜索