Django項目經常使用的logging配置javascript
settings.pycss
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' }, 'simple': { 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' }, 'collect': { 'format': '%(message)s' } }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], # 只有在Django debug爲True時纔在屏幕打印日誌 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'default': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日誌文件 'maxBytes': 1024 * 1024 * 50, # 日誌大小 50M 'backupCount': 3, 'formatter': 'standard', 'encoding': 'utf-8', }, 'error': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"), # 日誌文件 'maxBytes': 1024 * 1024 * 50, # 日誌大小 50M 'backupCount': 5, 'formatter': 'standard', 'encoding': 'utf-8', }, 'collect': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"), 'maxBytes': 1024 * 1024 * 50, # 日誌大小 50M 'backupCount': 5, 'formatter': 'collect', 'encoding': "utf-8" } }, 'loggers': { # 默認的logger應用以下配置 '': { 'handlers': ['default', 'console', 'error'], # 上線以後能夠把'console'移除 'level': 'DEBUG', 'propagate': True, }, # 名爲 'collect'的logger還單獨處理 'collect': { 'handlers': ['console', 'collect'], 'level': 'INFO', } }, }
Python logger流示圖html
使用:前端
settings.pyjava
""" Django settings for about_middleware project. Generated by 'django-admin startproject' using Django 2.0.1. For more information on this file, see https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 's011rs!(ga_n!j#*1@!-c2is3)xaw()87bpj=ffjhel^$vzi5v' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True # 真正上線 這是 false ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 註冊兩個自定義的中間件 'my_middleware.MD1', 'my_middleware.MD2', ] # 中間件 https://www.cnblogs.com/liwenzhou/p/8761803.html from django.middleware.security import SecurityMiddleware from django.middleware.csrf import CsrfViewMiddleware from django.middleware.clickjacking import XFrameOptionsMiddleware # process_request(self,request) # process_view(self, request, view_func, view_args, view_kwargs) # process_template_response(self,request,response) # process_exception(self, request, exception) # process_response(self, request, response) ROOT_URLCONF = 'about_middleware.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'about_middleware.wsgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' # https://www.cnblogs.com/liwenzhou/p/8763264.html # django 的日誌配置項 BASE_LOG_DIR = os.path.join(BASE_DIR,'log') LOGGING = { 'version': 1, # 保留字 'disable_existing_loggers': False, # 禁用已經存在的 logger 實例 'formatters': { # 詳細的日誌格式 'standard': { 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' }, # 簡單的日誌格式 'simple': { 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' }, # 定義一個特殊的日誌格式 'collect': { 'format': '%(message)s' } }, # 過濾器 'filters': { # DEBUG = True 的狀況 才過濾 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, # 處理器 'handlers': { # 在終端打印 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], # 只有在Django debug爲True時纔在屏幕打印日誌 'class': 'logging.StreamHandler', 'formatter': 'simple' }, # 默認 'default': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日誌文件 'maxBytes': 1024 * 1024 * 50, # 日誌大小 50M 通常配500M 'backupCount': 3, # 最多備份3個 'formatter': 'standard', 'encoding': 'utf-8', }, # 專門用來記 錯誤日誌 'error': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"), # 日誌文件 'maxBytes': 1024 * 1024 * 50, # 日誌大小 50M 'backupCount': 5, 'formatter': 'standard', 'encoding': 'utf-8', }, # 專門 定義一個 收集特定信息的日誌 'collect': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自動切 'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"), 'maxBytes': 1024 * 1024 * 50, # 日誌大小 50M 'backupCount': 5, 'formatter': 'collect', 'encoding': "utf-8" } }, 'loggers': { # 默認的logger應用以下配置 '': { 'handlers': ['default', 'console', 'error'], # 上線以後能夠把'console'移除 'level': 'DEBUG', 'propagate': True, # 向不向更高級別的logger傳遞 }, # 名爲 'collect'的logger還單獨處理 'collect': { 'handlers': ['console', 'collect'], 'level': 'INFO', } }, }
views.pypython
from django.shortcuts import render,HttpResponse # Create your views here. import logging # 生成一個以當前文件名爲名字的logger實例 logger = logging.getLogger(__name__) collect_logger = logging.getLogger('collect') # 生成一個名爲collect的實例 def index(requset): logger.debug('一個debug萌萌的請求...') logger.info('一個info萌萌的請求...') ''' 這是視圖函數index的doc信息 :param requset: :return: ''' print('@'*120) print('這是app01裏面的index函數') # print(requset.s9) # raise ValueError('hehe,拋異常') # return HttpResponse('OK') rep = HttpResponse('OK') collect_logger.info('這是collect_logger日誌') collect_logger.info('hello:collect') # def render(): # return HttpResponse('不經常使用') # # rep.render = render return rep
settings.pymysql
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ]
項目/staticjquery
/plugins/sweetalert # 插件 git
下載 dist css js 引入 github
https://github.com/lipis/bootstrap-sweetalert
https://lipis.github.io/bootstrap-sweetalert/
/bootstrap-3.3.7/css. fonts. js. # 下載
js ... # 下載
css ...
使用:
<script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/init_ajax.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <script src="/static/plugins/sweetalert/sweetalert.min.js"></script> <script type="text/javascript"> //給刪除按鈕綁定事件 $('.delete').click(function () { var id = $(this).parent().prev().prev().text(); var $currentTr = $(this).parent().parent(); swal({ title: "肯定要刪除嗎? ", text: "刪了就找不回來了", type: "warning", showCancelButton: true, // 顯不顯示取消按鈕 confirmButtonClass: "btn-danger", confirmButtonText: "是,就是刪除", //取消按鈕上的文字 closeOnConfirm: false }, function(){ $.ajax({ url:'/delete_publisher/', type:'post', data:{'publisher_id':id}, success:function (arg) { var ret = JSON.parse(arg); if(ret.status === 0){ $currentTr.remove(); swal("刪除成功!", "你能夠跑路了", "success"); }else{ swal(ret.msg, "你能夠嘗試在刪一次", "error"); } } }); }); }); </script>
settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'bms', 'HOST':'127.0.0.1', 'PORT':3306, 'USER':'root', 'PASSWORD':'123', } }
在項目bms __init__ 下設置
import pymysql
pymysql.install_as_MySQLdb()python manage.py makemigrations
python manage.py migrate
項目/static/init_ajax.js
// 從cooikie 取 csft token 的值 function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); // 將csrftoken 設置到ajax 請求頭中,後續的ajax請求就會自動攜帶這個csrf token function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
<script src="/static/jquery-3.2.1.min.js"></script>
<script src="/static/init_ajax.js"></script>
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() import datetime from app01 import models try: from django.db import transaction with transaction.atomic(): new_publisher = models.Publisher.objects.create(name="火星出版社") models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10) # 指定一個不存在的出版社id except Exception as e: print(str(e))
settings.py
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
項目/myscript.py
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() from app01 import models books = models.Book.objects.all() print(books)
測試數據,批量插入數據:
myscript.py
# -*- coding:utf-8 -*- import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() # 建立300個出版社 from app01 import models # Publisher.objects.create(name='水星第{}出版社'.format(i)) # obj = Publisher(name='火星出版社') # obj.save() # ret = [] # for i in range(300): # obj = Publisher(name='水星第{}出版社'.format(i)) # ret.append(obj) # ret = [models.Publisher(name='水星第{}出版社'.format(i)) for i in range(300)] # 批量建立300個出版社對象 # models.Publisher.objects.bulk_create(ret) # 只提交一次 # 建立300本書 import random ret = [models.Book(title='番茄物語{}'.format(i),price=random.randint(10, 90),publisher_id=1) for i in range(300)] models.Book.objects.bulk_create(ret)
項目/utils/mypage.py
''' 自定義分頁組件 ''' class Pagination(object): def __init__(self, data_num, current_page,url_prefix, per_page = 10, max_show = 11): """ 進行初始化 :param data_num: 數據總數 :param current_page: 當前頁 :param url_prefix: 生成得頁碼得連接前綴 :param per_page: 每頁顯示多少條數據 :param max_show: 頁面最多顯示多少個頁碼 """ self.data_num = data_num self.per_page = per_page self.max_show = max_show self.url_prefix = url_prefix # 把頁碼數算出來 self.page_num, more = divmod(self.data_num, self.per_page) if more: self.page_num += 1 try: current_page = int(current_page) except Exception as e: current_page = 1 if current_page <= 0: # 若是頁面數是 負數 current_page = 1 elif current_page > self.page_num: # 若是頁面 大於 總頁面 current_page = self.page_num self.current_page = current_page # 頁碼數得一半 self.half_show = self.max_show // 2 if self.current_page - self.half_show <= 1: self.page_start = 1 self.page_end = self.max_show elif self.current_page + self.half_show >= self.page_num: # 若是右邊 越界了 self.page_start = self.page_num - self.max_show + 1 self.page_end = self.page_num else: self.page_start = self.current_page - self.half_show self.page_end = self.current_page + self.half_show @property def start(self): return (self.current_page-1) * self.per_page # 數據從哪開始切 @property def end(self): return self.current_page * self.per_page # 數據切到哪 def page_html(self): # 生成頁碼 li = [] # 加一個首頁 li.append('<li><a href="{}?page=1">首頁</a></li>'.format(self.url_prefix)) # 加一個上一頁 if self.current_page == 1: li.append( '<li class="disabled"><a href="#"><span aria-hidden="true">«</span></a></li>') else: li.append('<li><a href="{0}?page={1}"><span aria-hidden="true">«</span></a></li>'.format( self.url_prefix,self.current_page - 1)) for i in range(self.page_start, self.page_end + 1): if i == self.current_page: tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix,i) else: tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix,i) li.append(tmp) # 加一個下一頁 if self.current_page == self.page_num: li.append( '<li class="disabled"><a href="#"><span aria-hidden="true">»</span></a></li>') else: li.append('<li><a href="{0}?page={1}"><span aria-hidden="true">»</span></a></li>'.format(self.url_prefix, self.current_page + 1)) li.append('<li><a href="{0}?page={1}">尾頁</a></li>'.format(self.url_prefix,self.page_num)) return "".join(li)
views.py
def publisher_list(request): data = Publisher.objects.all() data_num = data.count() # 數據得總數 current_page = request.GET.get('page', 1) from utils import mypage obj = mypage.Pagination(data_num,current_page,request.path) publisher_list = data[obj.start:obj.end] page_html = obj.page_html() return render( request, 'publisher_list.html', {'publisher_list': publisher_list,'page_html':page_html} )
publisher_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>publisher_list</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/plugins/sweetalert/sweetalert.css"> <style type="text/css"> .sweet-alert h2{padding-top: 20px;} </style> </head> <body> <a href="/logout">註銷</a> <div class="container"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>ID</th> <th>出版社名稱</th> <th>操做</th> </tr> </thead> <tbody> {% for publisher in publisher_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ publisher.id }}</td> <td>{{ publisher.name }}</td> <td> {# https://github.com/lipis/bootstrap-sweetalert #} <button class="btn btn-danger delete">刪除</button> </td> </tr> {% endfor %} </tbody> </table> <nav aria-label="..."> <ul class="pagination"> {{ page_html|safe }} </ul> </nav> </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/init_ajax.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <script src="/static/plugins/sweetalert/sweetalert.min.js"></script> <script type="text/javascript"> //給刪除按鈕綁定事件 $('.delete').click(function () { var id = $(this).parent().prev().prev().text(); var $currentTr = $(this).parent().parent(); swal({ title: "肯定要刪除嗎? ", text: "刪了就找不回來了", type: "warning", showCancelButton: true, // 顯不顯示取消按鈕 confirmButtonClass: "btn-danger", confirmButtonText: "是,就是刪除", //取消按鈕上的文字 closeOnConfirm: false }, function(){ $.ajax({ url:'/delete_publisher/', type:'post', data:{'publisher_id':id}, success:function (arg) { var ret = JSON.parse(arg); if(ret.status === 0){ $currentTr.remove(); swal("刪除成功!", "你能夠跑路了", "success"); }else{ swal(ret.msg, "你能夠嘗試在刪一次", "error"); } } }); }); }); </script> </body> </html>
re_path(r'^book_list/',views.BookList.as_view(),name="book_list"),
# 類視圖 要調用as_view()
# 以ip和端口後面什麼都沒有,就能匹配上url
re_path(r'^$',views.publisher_list),
views.py
# 使用django 內置得分頁 from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger class BookList(View): @method_decorator(check_login) def get(self,request): current_page = request.GET.get('page',1) data = Book.objects.all() # 用內置得分頁類 獲得一個分頁對象 page_obj = Paginator(data,10) try: # 嘗試去取 current_page ret = page_obj.page(current_page) except PageNotAnInteger: ret = page_obj.page(1) # 返回第一頁 except EmptyPage: ret = page_obj.page(page_obj.num_pages) # 返回最後一頁 return render(request,'book_list2.html',{'book_list':ret,})
book_list2.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>book_list</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <h1>這是書籍列表頁</h1> <a href="/logout">註銷</a> <div class="container"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>ID</th> <th>書籍名稱</th> </tr> </thead> <tbody> {% for book in book_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.id }}</td> <td>{{ book.title }}</td> </tr> {% endfor %} </tbody> </table> <nav aria-label="..."> <ul class="pagination"> {% if book_list.has_previous %} <li><a href="/book_list?page={{ book_list.previous_page_number }}">«</a></li> {% else %} <li class="disabled"><a href="#">«</a></li> {% endif %} <li class="active"><a href="/book_list?page={{ book_list.number }}">{{ book_list.number }}</a></li> {% if book_list.has_next %} <li><a href="/book_list?page={{ book_list.next_page_number}}">»</a></li> {% else %} <li class="disabled"><a href="#">»</a></li> {% endif %} </ul> </nav> </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </body> </html>
http://www.cnblogs.com/wupeiqi/articles/5246483.html
因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行view中的操做,而是直接從內存或者Redis中以前緩存的內容拿到,並返回。
Django中提供了6種緩存方式:
一、配置
a、開發調試
# 此爲開始調試用,實際內部不作任何操做 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎 'TIMEOUT': 300, # 緩存超時時間(默認300,None表示永不過時,0表示當即過時) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大緩存個數(默認300) 'CULL_FREQUENCY': 3, # 緩存到達最大個數以後,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認3) }, 'KEY_PREFIX': '', # 緩存key的前綴(默認空) 'VERSION': 1, # 緩存key的版本(默認1) 'KEY_FUNCTION' 函數名 # 生成key的函數(默認函數會生成爲:【前綴:版本:key】) } } # 自定義key def default_key_func(key, key_prefix, version): """ Default function to generate keys. Constructs the key used by all other methods. By default it prepends the `key_prefix'. KEY_FUNCTION can be used to specify an alternate function with custom key making behavior. """ return '%s:%s:%s' % (key_prefix, version, key) def get_key_func(key_func): """ Function to decide which key function to use. Defaults to ``default_key_func``. """ if key_func is not None: if callable(key_func): return key_func else: return import_string(key_func) return default_key_func
b、內存
# 此緩存將內容保存至內存的變量中 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'unique-snowflake', } } # 注:其餘配置同開發調試版本
c、文件
# 此緩存將內容保存至文件 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/django_cache', } } # 注:其餘配置同開發調試版本
d、數據庫
# 此緩存將內容保存至數據庫 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'my_cache_table', # 數據庫表 } } # 注:執行建立表命令 python manage.py createcachetable
e、Memcache緩存(python-memcached模塊)
# 此緩存使用python-memcached模塊鏈接memcache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'unix:/tmp/memcached.sock', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': [ '172.19.26.240:11211', '172.19.26.242:11211', ] } }
f、Memcache緩存(pylibmc模塊)
# 此緩存使用pylibmc模塊鏈接memcache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': '127.0.0.1:11211', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': '/tmp/memcached.sock', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': [ '172.19.26.240:11211', '172.19.26.242:11211', ] } }
g. Redis緩存(依賴:pip3 install django-redis)
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100} # "PASSWORD": "密碼", } } }
from django_redis import get_redis_connection conn = get_redis_connection("default")
二、應用
a. 全站使用
使用中間件,通過一系列的認證等操做,若是內容在緩存中存在,則使用FetchFromCacheMiddleware獲取內容並返回給用戶,當返回給用戶以前,判斷緩存中是否已經存在,若是不存在則UpdateCacheMiddleware會將緩存保存至緩存,從而實現全站緩存 MIDDLEWARE = [ 'django.middleware.cache.UpdateCacheMiddleware', # 其餘中間件... 'django.middleware.cache.FetchFromCacheMiddleware', ] CACHE_MIDDLEWARE_ALIAS = "" CACHE_MIDDLEWARE_SECONDS = "" CACHE_MIDDLEWARE_KEY_PREFIX = ""
b. 單獨視圖緩存
方式一: from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request): ... 方式二: from django.views.decorators.cache import cache_page urlpatterns = [ url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)), ]
c、局部視圖使用
a. 引入TemplateTag {% load cache %} b. 使用緩存 {% cache 5000 緩存key %} 緩存內容 {% endcache %}
更多:猛擊這裏
因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行view中的操做,而是直接從內存或者Redis中以前緩存的內容拿到,並返回。
Django中提供了6種緩存方式:
通用配置
'TIMEOUT': 300, # 緩存超時時間(默認300,None表示永不過時,0表示當即過時) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大緩存個數(默認300) 'CULL_FREQUENCY': 3, # 緩存到達最大個數以後,剔除緩存個數的比例,即:1/CULL_FREQUENCY(默認3) }, 'KEY_PREFIX': '', # 緩存key的前綴(默認空) 'VERSION': 1, # 緩存key的版本(默認1) 'KEY_FUNCTION' 函數名 # 生成key的函數(默認函數會生成爲:【前綴:版本:key】)
以上六中模式均可以使用
自定義key
def default_key_func(key, key_prefix, version): """ Default function to generate keys. Constructs the key used by all other methods. By default it prepends the `key_prefix'. KEY_FUNCTION can be used to specify an alternate function with custom key making behavior. """ return '%s:%s:%s' % (key_prefix, version, key) def get_key_func(key_func): """ Function to decide which key function to use. Defaults to ``default_key_func``. """ if key_func is not None: if callable(key_func): return key_func else: return import_string(key_func) return default_key_func
# 此爲開始調試用,實際內部不作任何操做 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎 通用配置 } }
# 此緩存將內容保存至內存的變量中 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 'LOCATION': 'unique-snowflake', 通用配置 } } # 注:其餘配置同開發調試版本
# 此緩存將內容保存至文件 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/django_cache', 通用配置 } } # 注:其餘配置同開發調試版本
# 此緩存將內容保存至數據庫 # 配置: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'my_cache_table', # 數據庫表 通用配置 } } # 注:執行建立表命令 python manage.py createcachetable
# 此緩存使用python-memcached模塊鏈接memcache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'unix:/tmp/memcached.sock', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': [ '172.19.26.240:11211', '172.19.26.242:11211', ] } }
# 此緩存使用pylibmc模塊鏈接memcache CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': '127.0.0.1:11211', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': '/tmp/memcached.sock', } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', 'LOCATION': [ '172.19.26.240:11211', '172.19.26.242:11211', ] } }
from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request): ...
即經過裝飾器的方式實現,導入模塊以後,在須要緩存的函數前加@cache_page(60 * 15) 60*15表示緩存時間是15分鐘
例子以下:
from django.views.decorators.cache import cache_page @cache_page(10) def cache(request): import time ctime = time.time() return render(request,"cache.html",{"ctime":ctime})
前端頁面以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> </body> </html>
這樣在前端頁面在獲取的ctime的時候就會被緩存10秒鐘,10秒鐘以後纔會變化,可是這樣的話就至關月全部的調用ctime的地方都被緩存了
引入TemplateTag {% load cache %} 使用緩存 {% cache 5000 緩存key %} 緩存內容 {% endcache %}
更改前端代碼以下:
{% load cache %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ ctime }}</h1> <h1>{{ ctime }}</h1> {% cache 10 c1 %} <h1>{{ ctime }}</h1> {% endcache %} </body> </html>
這樣就實現了最後一個ctime緩存,其餘兩個不緩存
全站緩存的時候,須要在中間件的最上面添加:
'django.middleware.cache.UpdateCacheMiddleware',
在中間件的最下面添加:
'django.middleware.cache.FetchFromCacheMiddleware',
其中'django.middleware.cache.UpdateCacheMiddleware'裏面只有process_response方法,在'django.middleware.cache.FetchFromCacheMiddleware'中只有process_request方法,因此最開始是直接跳過UpdateCacheMiddleware,而後從第一個到最後一箇中間件的resquest,第一次沒有緩存座椅匹配urls路由關係依次進過中間件的process_view,到達views函數,再通過process_exception最後通過response,到達FetchFromCacheMiddleware
使用中間件,通過一系列的認證等操做,若是內容在緩存中存在,則使用FetchFromCacheMiddleware獲取內容並返回給用戶,當返回給用戶以前,判斷緩存中是否已經存在,若是不存在則UpdateCacheMiddleware會將緩存保存至緩存,從而實現全站緩存
MIDDLEWARE
=
[
'django.middleware.cache.UpdateCacheMiddleware'
,
#放到第一個中間件位置
# 其餘中間件...
'django.middleware.cache.FetchFromCacheMiddleware'
,
#放到最後一個
]
CACHE_MIDDLEWARE_ALIAS
=
""
CACHE_MIDDLEWARE_SECONDS
=
"" # 可設置緩存時間
CACHE_MIDDLEWARE_KEY_PREFIX
=
""