一、logging配置

Django项目常用的logging配置

settings.py

  1. LOGGING = {
  2. 'version': 1,
  3. 'disable_existing_loggers': False,
  4. 'formatters': {
  5. 'standard': {
  6. 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
  7. '[%(levelname)s][%(message)s]'
  8. },
  9. 'simple': {
  10. 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
  11. },
  12. 'collect': {
  13. 'format': '%(message)s'
  14. }
  15. },
  16. 'filters': {
  17. 'require_debug_true': {
  18. '()': 'django.utils.log.RequireDebugTrue',
  19. },
  20. },
  21. 'handlers': {
  22. 'console': {
  23. 'level': 'DEBUG',
  24. 'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志
  25. 'class': 'logging.StreamHandler',
  26. 'formatter': 'simple'
  27. },
  28. 'default': {
  29. 'level': 'INFO',
  30. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  31. 'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日志文件
  32. 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
  33. 'backupCount': 3,
  34. 'formatter': 'standard',
  35. 'encoding': 'utf-8',
  36. },
  37. 'error': {
  38. 'level': 'ERROR',
  39. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  40. 'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"), # 日志文件
  41. 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
  42. 'backupCount': 5,
  43. 'formatter': 'standard',
  44. 'encoding': 'utf-8',
  45. },
  46. 'collect': {
  47. 'level': 'INFO',
  48. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  49. 'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
  50. 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
  51. 'backupCount': 5,
  52. 'formatter': 'collect',
  53. 'encoding': "utf-8"
  54. }
  55. },
  56. 'loggers': {
  57. # 默认的logger应用如下配置
  58. '': {
  59. 'handlers': ['default', 'console', 'error'], # 上线之后可以把'console'移除
  60. 'level': 'DEBUG',
  61. 'propagate': True,
  62. },
  63. # 名为 'collect'的logger还单独处理
  64. 'collect': {
  65. 'handlers': ['console', 'collect'],
  66. 'level': 'INFO',
  67. }
  68. },
  69. }

Python logger流示图

使用:

settings.py

  1. """
  2. Django settings for about_middleware project.
  3.  
  4. Generated by 'django-admin startproject' using Django 2.0.1.
  5.  
  6. For more information on this file, see
  7. https://docs.djangoproject.com/en/2.0/topics/settings/
  8.  
  9. For the full list of settings and their values, see
  10. https://docs.djangoproject.com/en/2.0/ref/settings/
  11. """
  12.  
  13. import os
  14.  
  15. # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
  16. BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  17.  
  18. # Quick-start development settings - unsuitable for production
  19. # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
  20.  
  21. # SECURITY WARNING: keep the secret key used in production secret!
  22. SECRET_KEY = 's011rs!(ga_n!j#*1@!-c2is3)xaw()87bpj=ffjhel^$vzi5v'
  23.  
  24. # SECURITY WARNING: don't run with debug turned on in production!
  25. DEBUG = True # 真正上线 这是 false
  26.  
  27. ALLOWED_HOSTS = []
  28.  
  29. # Application definition
  30.  
  31. INSTALLED_APPS = [
  32. 'django.contrib.admin',
  33. 'django.contrib.auth',
  34. 'django.contrib.contenttypes',
  35. 'django.contrib.sessions',
  36. 'django.contrib.messages',
  37. 'django.contrib.staticfiles',
  38. 'app01.apps.App01Config',
  39. ]
  40.  
  41. MIDDLEWARE = [
  42. 'django.middleware.security.SecurityMiddleware',
  43. 'django.contrib.sessions.middleware.SessionMiddleware',
  44. 'django.middleware.common.CommonMiddleware',
  45. 'django.middleware.csrf.CsrfViewMiddleware',
  46. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  47. 'django.contrib.messages.middleware.MessageMiddleware',
  48. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  49.  
  50. # 注册两个自定义的中间件
  51. 'my_middleware.MD1',
  52. 'my_middleware.MD2',
  53.  
  54. ]
  55. # 中间件 https://www.cnblogs.com/liwenzhou/p/8761803.html
  56.  
  57. from django.middleware.security import SecurityMiddleware
  58. from django.middleware.csrf import CsrfViewMiddleware
  59. from django.middleware.clickjacking import XFrameOptionsMiddleware
  60.  
  61. # process_request(self,request)
  62. # process_view(self, request, view_func, view_args, view_kwargs)
  63. # process_template_response(self,request,response)
  64. # process_exception(self, request, exception)
  65. # process_response(self, request, response)
  66.  
  67. ROOT_URLCONF = 'about_middleware.urls'
  68.  
  69. TEMPLATES = [
  70. {
  71. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  72. 'DIRS': [os.path.join(BASE_DIR, 'templates')]
  73. ,
  74. 'APP_DIRS': True,
  75. 'OPTIONS': {
  76. 'context_processors': [
  77. 'django.template.context_processors.debug',
  78. 'django.template.context_processors.request',
  79. 'django.contrib.auth.context_processors.auth',
  80. 'django.contrib.messages.context_processors.messages',
  81. ],
  82. },
  83. },
  84. ]
  85.  
  86. WSGI_APPLICATION = 'about_middleware.wsgi.application'
  87.  
  88. # Database
  89. # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
  90.  
  91. DATABASES = {
  92. 'default': {
  93. 'ENGINE': 'django.db.backends.sqlite3',
  94. 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
  95. }
  96. }
  97.  
  98. # Password validation
  99. # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
  100.  
  101. AUTH_PASSWORD_VALIDATORS = [
  102. {
  103. 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
  104. },
  105. {
  106. 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
  107. },
  108. {
  109. 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
  110. },
  111. {
  112. 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
  113. },
  114. ]
  115.  
  116. # Internationalization
  117. # https://docs.djangoproject.com/en/2.0/topics/i18n/
  118.  
  119. LANGUAGE_CODE = 'en-us'
  120.  
  121. TIME_ZONE = 'UTC'
  122.  
  123. USE_I18N = True
  124.  
  125. USE_L10N = True
  126.  
  127. USE_TZ = True
  128.  
  129. # Static files (CSS, JavaScript, Images)
  130. # https://docs.djangoproject.com/en/2.0/howto/static-files/
  131.  
  132. STATIC_URL = '/static/'
  133.  
  134. # https://www.cnblogs.com/liwenzhou/p/8763264.html
  135. # django 的日志配置项
  136. BASE_LOG_DIR = os.path.join(BASE_DIR,'log')
  137. LOGGING = {
  138. 'version': 1, # 保留字
  139. 'disable_existing_loggers': False, # 禁用已经存在的 logger 实例
  140. 'formatters': {
  141. # 详细的日志格式
  142. 'standard': {
  143. 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
  144. '[%(levelname)s][%(message)s]'
  145. },
  146. # 简单的日志格式
  147. 'simple': {
  148. 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
  149. },
  150. # 定义一个特殊的日志格式
  151. 'collect': {
  152. 'format': '%(message)s'
  153. }
  154. },
  155. # 过滤器
  156. 'filters': {
  157. # DEBUG = True 的情况 才过滤
  158. 'require_debug_true': {
  159. '()': 'django.utils.log.RequireDebugTrue',
  160. },
  161. },
  162. # 处理器
  163. 'handlers': {
  164. # 在终端打印
  165. 'console': {
  166. 'level': 'DEBUG',
  167. 'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志
  168. 'class': 'logging.StreamHandler',
  169. 'formatter': 'simple'
  170. },
  171. # 默认
  172. 'default': {
  173. 'level': 'INFO',
  174. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  175. 'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"), # 日志文件
  176. 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 一般配500M
  177. 'backupCount': 3, # 最多备份3个
  178. 'formatter': 'standard',
  179. 'encoding': 'utf-8',
  180. },
  181. # 专门用来记 错误日志
  182. 'error': {
  183. 'level': 'ERROR',
  184. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  185. 'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"), # 日志文件
  186. 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
  187. 'backupCount': 5,
  188. 'formatter': 'standard',
  189. 'encoding': 'utf-8',
  190. },
  191. # 专门 定义一个 收集特定信息的日志
  192. 'collect': {
  193. 'level': 'INFO',
  194. 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
  195. 'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
  196. 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
  197. 'backupCount': 5,
  198. 'formatter': 'collect',
  199. 'encoding': "utf-8"
  200. }
  201. },
  202. 'loggers': {
  203. # 默认的logger应用如下配置
  204. '': {
  205. 'handlers': ['default', 'console', 'error'], # 上线之后可以把'console'移除
  206. 'level': 'DEBUG',
  207. 'propagate': True, # 向不向更高级别的logger传递
  208. },
  209. # 名为 'collect'的logger还单独处理
  210. 'collect': {
  211. 'handlers': ['console', 'collect'],
  212. 'level': 'INFO',
  213. }
  214. },
  215. }

settings

views.py

  1. from django.shortcuts import render,HttpResponse
  2.  
  3. # Create your views here.
  4.  
  5. import logging
  6. # 生成一个以当前文件名为名字的logger实例
  7. logger = logging.getLogger(__name__)
  8. collect_logger = logging.getLogger('collect') # 生成一个名为collect的实例
  9.  
  10. def index(requset):
  11. logger.debug('一个debug萌萌的请求...')
  12. logger.info('一个info萌萌的请求...')
  13. '''
  14. 这是视图函数index的doc信息
  15. :param requset:
  16. :return:
  17. '''
  18. print('@'*120)
  19. print('这是app01里面的index函数')
  20. # print(requset.s9)
  21.  
  22. # raise ValueError('hehe,抛异常')
  23.  
  24. # return HttpResponse('OK')
  25.  
  26. rep = HttpResponse('OK')
  27. collect_logger.info('这是collect_logger日志')
  28. collect_logger.info('hello:collect')
  29.  
  30. # def render():
  31. # return HttpResponse('不常用')
  32. #
  33. # rep.render = render
  34. return rep

views

二、静态文件配置

settings.py

  1. STATIC_URL = '/static/'
  2. STATICFILES_DIRS = [
  3. os.path.join(BASE_DIR,'static')
  4. ]

项目/static

    /plugins/sweetalert    # 插件

 下载 dist css js 引入

  1. https://github.com/lipis/bootstrap-sweetalert
    https://lipis.github.io/bootstrap-sweetalert/

      

    /bootstrap-3.3.7/css. fonts. js.   # 下载

    js ...       # 下载

    css ...

使用:

  1. <script src="/static/jquery-3.2.1.min.js"></script>
  2. <script src="/static/init_ajax.js"></script>
  3. <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
  4. <script src="/static/plugins/sweetalert/sweetalert.min.js"></script>
  5.  
  6. <script type="text/javascript">
  7. //给删除按钮绑定事件
  8. $('.delete').click(function () {
  9. var id = $(this).parent().prev().prev().text();
  10. var $currentTr = $(this).parent().parent();
  11. swal({
  12. title: "确定要删除吗? ",
  13. text: "删了就找不回来了",
  14. type: "warning",
  15. showCancelButton: true, // 显不显示取消按钮
  16. confirmButtonClass: "btn-danger",
  17. confirmButtonText: "是,就是删除", //取消按钮上的文字
  18. closeOnConfirm: false
  19. },
  20. function(){
  21. $.ajax({
  22. url:'/delete_publisher/',
  23. type:'post',
  24. data:{'publisher_id':id},
  25. success:function (arg) {
  26. var ret = JSON.parse(arg);
  27. if(ret.status === 0){
  28. $currentTr.remove();
  29. swal("删除成功!", "你可以跑路了", "success");
  30. }else{
  31. swal(ret.msg, "你可以尝试在删一次", "error");
  32. }
  33. }
  34. });
  35. });
  36. });
  37.  
  38. </script> 

三、mysql配置

settings.py

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME': 'bms',
  5. 'HOST':'127.0.0.1',
  6. 'PORT':3306,
  7. 'USER':'root',
  8. 'PASSWORD':'',
  9. }
  10. }
  1. 在项目bms __init__ 下设置
    import pymysql
    pymysql.install_as_MySQLdb()
  1. python manage.py makemigrations
    python manage.py migrate

四、ajax post (csrf-token)请求前配置

  项目/static/init_ajax.js

  1. // 从cooikie 取 csft token 的值
  2. function getCookie(name) {
  3. var cookieValue = null;
  4. if (document.cookie && document.cookie !== '') {
  5. var cookies = document.cookie.split(';');
  6. for (var i = 0; i < cookies.length; i++) {
  7. var cookie = jQuery.trim(cookies[i]);
  8. // Does this cookie string begin with the name we want?
  9. if (cookie.substring(0, name.length + 1) === (name + '=')) {
  10. cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  11. break;
  12. }
  13. }
  14. }
  15. return cookieValue;
  16. }
  17. var csrftoken = getCookie('csrftoken');
  18.  
  19. // 将csrftoken 设置到ajax 请求头中,后续的ajax请求就会自动携带这个csrf token
  20. function csrfSafeMethod(method) {
  21. // these HTTP methods do not require CSRF protection
  22. return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  23. }
  24.  
  25. $.ajaxSetup({
  26. beforeSend: function (xhr, settings) {
  27. if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
  28. xhr.setRequestHeader("X-CSRFToken", csrftoken);
  29. }
  30. }
  31. });
  1. <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/init_ajax.js"></script>

五、事务

  1. import os
  2.  
  3. if __name__ == '__main__':
  4. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
  5. import django
  6. django.setup()
  7.  
  8. import datetime
  9. from app01 import models
  10.  
  11. try:
  12. from django.db import transaction
  13. with transaction.atomic():
  14. new_publisher = models.Publisher.objects.create(name="火星出版社")
  15. models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
  16. except Exception as e:
  17. print(str(e))

六、Django终端打印SQL语句

settings.py

  1. LOGGING = {
  2. 'version': 1,
  3. 'disable_existing_loggers': False,
  4. 'handlers': {
  5. 'console':{
  6. 'level':'DEBUG',
  7. 'class':'logging.StreamHandler',
  8. },
  9. },
  10. 'loggers': {
  11. 'django.db.backends': {
  12. 'handlers': ['console'],
  13. 'propagate': True,
  14. 'level':'DEBUG',
  15. },
  16. }
  17. }

七、在Python脚本中调用Django环境

项目/myscript.py

  1. import os
  2.  
  3. if __name__ == '__main__':
  4. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
  5. import django
  6. django.setup()
  7.  
  8. from app01 import models
  9.  
  10. books = models.Book.objects.all()
  11. print(books)

测试数据,批量插入数据:

myscript.py

  1. # -*- coding:utf-8 -*-
  2. import os
  3.  
  4. if __name__ == '__main__':
  5. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
  6. import django
  7. django.setup()
  8.  
  9. # 创建300个出版社
  10. from app01 import models
  11.  
  12. # Publisher.objects.create(name='水星第{}出版社'.format(i))
  13.  
  14. # obj = Publisher(name='火星出版社')
  15. # obj.save()
  16.  
  17. # ret = []
  18. # for i in range(300):
  19. # obj = Publisher(name='水星第{}出版社'.format(i))
  20. # ret.append(obj)
  21.  
  22. # ret = [models.Publisher(name='水星第{}出版社'.format(i)) for i in range(300)]
  23.  
  24. # 批量创建300个出版社对象
  25. # models.Publisher.objects.bulk_create(ret) # 只提交一次
  26.  
  27. # 创建300本书
  28. import random
  29. ret = [models.Book(title='番茄物语{}'.format(i),price=random.randint(10, 90),publisher_id=1) for i in range(300)]
  30. models.Book.objects.bulk_create(ret)

八、自定义分页组件

项目/utils/mypage.py

  1. '''
  2. 自定义分页组件
  3.  
  4. '''
  5. class Pagination(object):
  6.  
  7. def __init__(self, data_num, current_page,url_prefix, per_page = 10, max_show = 11):
  8. """
  9. 进行初始化
  10. :param data_num: 数据总数
  11. :param current_page: 当前页
  12. :param url_prefix: 生成得页码得链接前缀
  13. :param per_page: 每页显示多少条数据
  14. :param max_show: 页面最多显示多少个页码
  15. """
  16. self.data_num = data_num
  17. self.per_page = per_page
  18. self.max_show = max_show
  19. self.url_prefix = url_prefix
  20.  
  21. # 把页码数算出来
  22. self.page_num, more = divmod(self.data_num, self.per_page)
  23. if more:
  24. self.page_num += 1
  25.  
  26. try:
  27. current_page = int(current_page)
  28. except Exception as e:
  29. current_page = 1
  30. if current_page <= 0: # 如果页面数是 负数
  31. current_page = 1
  32. elif current_page > self.page_num: # 如果页面 大于 总页面
  33. current_page = self.page_num
  34. self.current_page = current_page
  35.  
  36. # 页码数得一半
  37. self.half_show = self.max_show // 2
  38.  
  39. if self.current_page - self.half_show <= 1:
  40. self.page_start = 1
  41. self.page_end = self.max_show
  42. elif self.current_page + self.half_show >= self.page_num: # 如果右边 越界了
  43. self.page_start = self.page_num - self.max_show + 1
  44. self.page_end = self.page_num
  45. else:
  46. self.page_start = self.current_page - self.half_show
  47. self.page_end = self.current_page + self.half_show
  48.  
  49. @property
  50. def start(self):
  51. return (self.current_page-1) * self.per_page # 数据从哪开始切
  52.  
  53. @property
  54. def end(self):
  55. return self.current_page * self.per_page # 数据切到哪
  56.  
  57. def page_html(self):
  58. # 生成页码
  59. li = []
  60. # 加一个首页
  61. li.append('<li><a href="{}?page=1">首页</a></li>'.format(self.url_prefix))
  62. # 加一个上一页
  63. if self.current_page == 1:
  64. li.append(
  65. '<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>')
  66. else:
  67. li.append('<li><a href="{0}?page={1}"><span aria-hidden="true">&laquo;</span></a></li>'.format(
  68. self.url_prefix,self.current_page - 1))
  69. for i in range(self.page_start, self.page_end + 1):
  70. if i == self.current_page:
  71. tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix,i)
  72. else:
  73. tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix,i)
  74. li.append(tmp)
  75. # 加一个下一页
  76. if self.current_page == self.page_num:
  77. li.append(
  78. '<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>')
  79. else:
  80. li.append('<li><a href="{0}?page={1}"><span aria-hidden="true">&raquo;</span></a></li>'.format(self.url_prefix,
  81. self.current_page + 1))
  82. li.append('<li><a href="{0}?page={1}">尾页</a></li>'.format(self.url_prefix,self.page_num))
  83.  
  84. return "".join(li)

views.py

  1. def publisher_list(request):
  2. data = Publisher.objects.all()
  3. data_num = data.count() # 数据得总数
  4. current_page = request.GET.get('page', 1)
  5. from utils import mypage
  6. obj = mypage.Pagination(data_num,current_page,request.path)
  7. publisher_list = data[obj.start:obj.end]
  8. page_html = obj.page_html()
  9. return render(
  10. request,
  11. 'publisher_list.html',
  12. {'publisher_list': publisher_list,'page_html':page_html}
  13. )

publisher_list.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>publisher_list</title>
  6. <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
  7. <link rel="stylesheet" href="/static/plugins/sweetalert/sweetalert.css">
  8. <style type="text/css">
  9. .sweet-alert h2{padding-top: 20px;}
  10. </style>
  11. </head>
  12. <body>
  13. <a href="/logout">注销</a>
  14. <div class="container">
  15. <table class="table table-bordered">
  16. <thead>
  17. <tr>
  18. <th>#</th>
  19. <th>ID</th>
  20. <th>出版社名称</th>
  21. <th>操作</th>
  22. </tr>
  23. </thead>
  24. <tbody>
  25. {% for publisher in publisher_list %}
  26. <tr>
  27. <td>{{ forloop.counter }}</td>
  28. <td>{{ publisher.id }}</td>
  29. <td>{{ publisher.name }}</td>
  30. <td>
  31. {# https://github.com/lipis/bootstrap-sweetalert #}
  32. <button class="btn btn-danger delete">删除</button>
  33. </td>
  34. </tr>
  35. {% endfor %}
  36.  
  37. </tbody>
  38. </table>
  39. <nav aria-label="...">
  40. <ul class="pagination">
  41. {{ page_html|safe }}
  42. </ul>
  43. </nav>
  44. </div>
  45.  
  46. <script src="/static/jquery-3.2.1.min.js"></script>
  47. <script src="/static/init_ajax.js"></script>
  48. <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
  49. <script src="/static/plugins/sweetalert/sweetalert.min.js"></script>
  50.  
  51. <script type="text/javascript">
  52. //给删除按钮绑定事件
  53. $('.delete').click(function () {
  54. var id = $(this).parent().prev().prev().text();
  55. var $currentTr = $(this).parent().parent();
  56. swal({
  57. title: "确定要删除吗? ",
  58. text: "删了就找不回来了",
  59. type: "warning",
  60. showCancelButton: true, // 显不显示取消按钮
  61. confirmButtonClass: "btn-danger",
  62. confirmButtonText: "是,就是删除", //取消按钮上的文字
  63. closeOnConfirm: false
  64. },
  65. function(){
  66. $.ajax({
  67. url:'/delete_publisher/',
  68. type:'post',
  69. data:{'publisher_id':id},
  70. success:function (arg) {
  71. var ret = JSON.parse(arg);
  72. if(ret.status === 0){
  73. $currentTr.remove();
  74. swal("删除成功!", "你可以跑路了", "success");
  75. }else{
  76. swal(ret.msg, "你可以尝试在删一次", "error");
  77. }
  78. }
  79. });
  80. });
  81. });
  82.  
  83. </script>
  84.  
  85. </body>
  86. </html>

九、django分页组件(CBV)

  1. re_path(r'^book_list/',views.BookList.as_view(),name="book_list"),
  1. # 类视图 要调用as_view()
  1. # 以ip和端口后面什么都没有,就能匹配上url
    re_path(r'^$',views.publisher_list),

views.py

  1. # 使用django 内置得分页
  2.  
  3. from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
  4.  
  5. class BookList(View):
  6.  
  7. @method_decorator(check_login)
  8. def get(self,request):
  9. current_page = request.GET.get('page',1)
  10. data = Book.objects.all()
  11.  
  12. # 用内置得分页类 得到一个分页对象
  13. page_obj = Paginator(data,10)
  14. try:
  15. # 尝试去取 current_page
  16. ret = page_obj.page(current_page)
  17. except PageNotAnInteger:
  18. ret = page_obj.page(1) # 返回第一页
  19. except EmptyPage:
  20. ret = page_obj.page(page_obj.num_pages) # 返回最后一页
  21.  
  22. return render(request,'book_list2.html',{'book_list':ret,})

book_list2.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>book_list</title>
  6. <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
  7. </head>
  8. <body>
  9. <h1>这是书籍列表页</h1>
  10. <a href="/logout">注销</a>
  11.  
  12. <div class="container">
  13. <table class="table table-bordered">
  14. <thead>
  15. <tr>
  16. <th>#</th>
  17. <th>ID</th>
  18. <th>书籍名称</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. {% for book in book_list %}
  23. <tr>
  24. <td>{{ forloop.counter }}</td>
  25. <td>{{ book.id }}</td>
  26. <td>{{ book.title }}</td>
  27. </tr>
  28. {% endfor %}
  29.  
  30. </tbody>
  31. </table>
  32. <nav aria-label="...">
  33. <ul class="pagination">
  34. {% if book_list.has_previous %}
  35. <li><a href="/book_list?page={{ book_list.previous_page_number }}">«</a></li>
  36. {% else %}
  37. <li class="disabled"><a href="#">«</a></li>
  38. {% endif %}
  39. <li class="active"><a href="/book_list?page={{ book_list.number }}">{{ book_list.number }}</a></li>
  40. {% if book_list.has_next %}
  41. <li><a href="/book_list?page={{ book_list.next_page_number}}">»</a></li>
  42. {% else %}
  43. <li class="disabled"><a href="#">»</a></li>
  44. {% endif %}
  45. </ul>
  46. </nav>
  47. </div>
  48.  
  49. <script src="/static/jquery-3.2.1.min.js"></script>
  50. <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
  51. </body>
  52. </html>

十、django缓存 - redis

http://www.cnblogs.com/wupeiqi/articles/5246483.html

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

  1. # 此为开始调试用,实际内部不做任何操作
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
  6. 'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
  7. 'OPTIONS':{
  8. 'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
  9. 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  10. },
  11. 'KEY_PREFIX': '', # 缓存key的前缀(默认空)
  12. 'VERSION': 1, # 缓存key的版本(默认1)
  13. 'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
  14. }
  15. }
  16.  
  17. # 自定义key
  18. def default_key_func(key, key_prefix, version):
  19. """
  20. Default function to generate keys.
  21.  
  22. Constructs the key used by all other methods. By default it prepends
  23. the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
  24. function with custom key making behavior.
  25. """
  26. return '%s:%s:%s' % (key_prefix, version, key)
  27.  
  28. def get_key_func(key_func):
  29. """
  30. Function to decide which key function to use.
  31.  
  32. Defaults to ``default_key_func``.
  33. """
  34. if key_func is not None:
  35. if callable(key_func):
  36. return key_func
  37. else:
  38. return import_string(key_func)
  39. return default_key_func

b、内存

  1. # 此缓存将内容保存至内存的变量中
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
  6. 'LOCATION': 'unique-snowflake',
  7. }
  8. }
  9.  
  10. # 注:其他配置同开发调试版本

c、文件

  1. # 此缓存将内容保存至文件
  2. # 配置:
  3.  
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
  7. 'LOCATION': '/var/tmp/django_cache',
  8. }
  9. }
  10. # 注:其他配置同开发调试版本

d、数据库

  1. # 此缓存将内容保存至数据库
  2.  
  3. # 配置:
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
  7. 'LOCATION': 'my_cache_table', # 数据库表
  8. }
  9. }
  10.  
  11. # 注:执行创建表命令 python manage.py createcachetable

e、Memcache缓存(python-memcached模块)

  1. # 此缓存使用python-memcached模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  13. 'LOCATION': 'unix:/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

f、Memcache缓存(pylibmc模块)

  1. # 此缓存使用pylibmc模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  13. 'LOCATION': '/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

g. Redis缓存(依赖:pip3 install django-redis)

  1. CACHES = {
  2. "default": {
  3. "BACKEND": "django_redis.cache.RedisCache",
  4. "LOCATION": "redis://127.0.0.1:6379",
  5. "OPTIONS": {
  6. "CLIENT_CLASS": "django_redis.client.DefaultClient",
  7. "CONNECTION_POOL_KWARGS": {"max_connections": 100}
  8. # "PASSWORD": "密码",
  9. }
  10. }
  11. }
  1. from django_redis import get_redis_connection
  2. conn = get_redis_connection("default")

2、应用

a. 全站使用

  1. 使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
  2.  
  3. MIDDLEWARE = [
  4. 'django.middleware.cache.UpdateCacheMiddleware',
  5. # 其他中间件...
  6. 'django.middleware.cache.FetchFromCacheMiddleware',
  7. ]
  8.  
  9. CACHE_MIDDLEWARE_ALIAS = ""
  10. CACHE_MIDDLEWARE_SECONDS = ""
  11. CACHE_MIDDLEWARE_KEY_PREFIX = ""

b. 单独视图缓存

  1. 方式一:
  2. from django.views.decorators.cache import cache_page
  3.  
  4. @cache_page(60 * 15)
  5. def my_view(request):
  6. ...
  7.  
  8. 方式二:
  9. from django.views.decorators.cache import cache_page
  10.  
  11. urlpatterns = [
  12. url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
  13. ]

c、局部视图使用

  1. a. 引入TemplateTag
  2.  
  3. {% load cache %}
  4.  
  5. b. 使用缓存
  6.  
  7. {% cache 5000 缓存key %}
  8. 缓存内容
  9. {% endcache %}

更多:猛击这里


django缓存配置

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

通用配置

  1. 'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
  2. 'OPTIONS':{
  3. 'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
  4. 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  5. },
  6. 'KEY_PREFIX': '', # 缓存key的前缀(默认空)
  7. 'VERSION': 1, # 缓存key的版本(默认1)
  8. 'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)

以上六中模式都可以使用

自定义key

  1. def default_key_func(key, key_prefix, version):
  2. """
  3. Default function to generate keys.
  4.  
  5. Constructs the key used by all other methods. By default it prepends
  6. the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
  7. function with custom key making behavior.
  8. """
  9. return '%s:%s:%s' % (key_prefix, version, key)
  10.  
  11. def get_key_func(key_func):
  12. """
  13. Function to decide which key function to use.
  14.  
  15. Defaults to ``default_key_func``.
  16. """
  17. if key_func is not None:
  18. if callable(key_func):
  19. return key_func
  20. else:
  21. return import_string(key_func)
  22. return default_key_func

开发调试

  1. # 此为开始调试用,实际内部不做任何操作
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
  6. 通用配置
  7. }
  8. }

内存

  1. # 此缓存将内容保存至内存的变量中
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
  6. 'LOCATION': 'unique-snowflake',
  7. 通用配置
  8. }
  9. }
  10.  
  11. # 注:其他配置同开发调试版本

文件

  1. # 此缓存将内容保存至文件
  2. # 配置:
  3.  
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
  7. 'LOCATION': '/var/tmp/django_cache',
  8. 通用配置
  9. }
  10. }
  11. # 注:其他配置同开发调试版本

数据库

  1. # 此缓存将内容保存至数据库
  2.  
  3. # 配置:
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
  7. 'LOCATION': 'my_cache_table', # 数据库表
  8. 通用配置
  9. }
  10. }
  11.  
  12. # 注:执行创建表命令 python manage.py createcachetable

Memcache缓存(python-memcached模块)

  1. # 此缓存使用python-memcached模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  13. 'LOCATION': 'unix:/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

Memcache缓存(pylibmc模块)

  1. # 此缓存使用pylibmc模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  13. 'LOCATION': '/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

缓存的应用

单独视图缓存

  1. from django.views.decorators.cache import cache_page
  2.  
  3. @cache_page(60 * 15)
  4. def my_view(request):
  5. ...

即通过装饰器的方式实现,导入模块之后,在需要缓存的函数前加@cache_page(60 * 15) 60*15表示缓存时间是15分钟

例子如下:

  1. from django.views.decorators.cache import cache_page
  2. @cache_page(10)
  3. def cache(request):
  4. import time
  5. ctime = time.time()
  6. return render(request,"cache.html",{"ctime":ctime})

前端页面如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h1>{{ ctime }}</h1>
  9. <h1>{{ ctime }}</h1>
  10. <h1>{{ ctime }}</h1>
  11.  
  12. </body>
  13. </html>

这样在前端页面在获取的ctime的时候就会被缓存10秒钟,10秒钟之后才会变化,但是这样的话就相当月所有的调用ctime的地方都被缓存了

局部缓存

  1. 引入TemplateTag
  2.  
  3. {% load cache %}
  4.  
  5. 使用缓存
  6.  
  7. {% cache 5000 缓存key %}
  8. 缓存内容
  9. {% endcache %}

更改前端代码如下:

  1. {% load cache %}
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Title</title>
  7. </head>
  8. <body>
  9. <h1>{{ ctime }}</h1>
  10. <h1>{{ ctime }}</h1>
  11. {% cache 10 c1 %}
  12. <h1>{{ ctime }}</h1>
  13. {% endcache %}
  14. </body>
  15. </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 = ""

Django - 常用配置的更多相关文章

  1. 最全的Django入门及常用配置

    Django 常用配置 Django 安装 pipx install django x 为python解释器版本2 or 3 如果你想安装指定版本的django,使用pip install djang ...

  2. django->基本操作和新建项目常用配置

    一.安装django pip install django==2.1.5 -U #安装django/升级最新版本 二.创建.启动django项目 django-admin startproject m ...

  3. Django常用命令及参数配置(Django 1.8.6)

    常用命令 #新建Django项目 django-admin startproject mysite(项目名) #新建一个APP cd mysite python manager.py startapp ...

  4. Django - 日志工作中常用配置

    工作中常用配置 # 日志配置 BASE_LOG_DIR = os.path.join(BASE_DIR, "log") LOGGING = { 'version': 1, # 保留 ...

  5. Django笔记&教程 1-2 二 常用配置

    Django 自学笔记兼学习教程第1章第2节--二 常用配置 点击查看教程总目录 新手建议简单浏览本文,不理解的建议跳过,不要强行理解. Django的设置涉及多个模块,需要了解Django的一些相关 ...

  6. django-debug-toolbar和Django 日志配置

    django-debug-toolbar介绍 django-debug-toolbar 是一组可配置的面板,可显示有关当前请求/响应的各种调试信息,并在单击时显示有关面板内容的更多详细信息. gith ...

  7. python 全栈开发,Day96(Django REST framework 视图,django logging配置,django-debug-toolbar使用指南)

    昨日内容回顾 1. Serializer(序列化) 1. ORM对应的query_set和ORM对象转换成JSON格式的数据 1. 在序列化类中定义自定义的字段:SerializerMethodFie ...

  8. Pycharm常用配置

    Pycharm常用配置 pycharm中的设置是可以导入和导出的,file>export settings 可以保存当前pycharm中的设置为jar文件,重装时可以直接import setti ...

  9. 12: nginx原理及常用配置

    1.1 nginx基本介绍 1.nginx高并发原理( 多进程+epoll实现高并发 ) 1. Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程. 2. 每个子进 ...

随机推荐

  1. 类加载器详解 (转至http://blog.csdn.net/jiangwei0910410003/article/details/17733153)

    首先来了解一下字节码和class文件的区别: 我们知道,新建一个java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的 ...

  2. R语言绘图边框

    在R语言中, 绘图边框一共有3个区域: device region : figure region : plot region   : 在描述不同区域大小的时候,有对应的不同参数: din : 返回d ...

  3. Winform appconfig修改后的更新问题

  4. MySQL数据库行去重复

    1.创立数据表

  5. db2

    关于3种导入导出操作进行简单的介绍:export:导出数据,支持IXF,DEL或WSFimport:导入数据,可以向表中导入数据,支持上面提到的4种文件类型.    load:导入数据,功能和impo ...

  6. JS怎样捕获浏览器关闭时间弹出自定义对话框

    <script type="text/javascript">window.onbeforeunload = function (e) { e = e || windo ...

  7. mysql通过mysqldump工具,对某个库下的表进行备份

    需求描述: 使用mysqldump工具对某个库下的表进行备份的方法. 操作过程: 1.通过mysqldump工具完成此目的 [mysql@redhat6 MysqlDb_Backup]$ mysqld ...

  8. 而桌面app向来是web前端开发开发人员下意识的避开方

    web前端语言的发展有目共睹, 从原来的pc web, 到后来的mobile SAP, 再到 nodejs,全站工程师应运而生. js快速而且稳健的发展让人不得不重视, 相应的前端开发人员的地位也越来 ...

  9. Java精选笔记_IO流(字节流、InputStream、OutputStream、字节文件、缓冲区输入输出流)

    字节流 操作图片数据就要用到字节流. 字符流使用的是字符数组char[],字节流使用的是字节数组byte[]. 字节流读写文件 针对文件的读写,JDK专门提供了两个类,分别是FileInputStre ...

  10. Redis(四)-- 集群

    一.Redis适合做企业级分布式缓存集群的条件 1.Redis内置哈希槽,有16384个哈希槽(0~16383),根据CRC16算法来确定这个集群中属于哪一个服务器来处理这个请求. 2.Redis提供 ...