当前位置: 首页 > news >正文

网页设计与网站建设在线考试石油大学东莞市做网站的公司哪家好

网页设计与网站建设在线考试石油大学,东莞市做网站的公司哪家好,建设银行宁波分行招聘网站,超酷 flash 网站Django框架中级 – 潘登同学的WEB框架 文章目录 Django框架中级 -- 潘登同学的WEB框架 中间件自定义中间件常用中间件process_view() 使用中间件进行URL过滤 Django生命周期生命周期分析 Django日志日志配置filter过滤器自定义filter 日志格式化formatter Django信号内置信号定…Django框架中级 – 潘登同学的WEB框架 文章目录 Django框架中级 -- 潘登同学的WEB框架 中间件自定义中间件常用中间件process_view() 使用中间件进行URL过滤 Django生命周期生命周期分析 Django日志日志配置filter过滤器自定义filter 日志格式化formatter Django信号内置信号定义与连接信号自定义信号 Django缓存安装Redis设置Django缓存全站缓存视图缓存模板缓存底层缓存缓存 API 应用 Session缓存 Celery配置Celery生产异步任务生产定时任务任务结果Django集成CeleryDjango-任务交给CeleryCelery 绑定参数Celery 钩子函数Celery 组装任务Celery 任务监控 DebugToolBarDebugToolBar 配置 中间件 AOPAspect Oriented Programming 面向切面编程是对业务逻辑的各个部分进行隔离从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率。可以实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。 面向切面编程就是将交叉业务逻辑封装成切面利用AOP的功能将切面植入到主业务逻辑中。所谓交叉业务逻辑是指通用的与主业务逻辑无关的代码如安全检查事务日志等。若不使用AOP则会出现代码纠缠即交叉业务逻辑与主业务逻辑混合在一起。这样会使业务逻辑变得混杂不清。 Django的中间件就是应用AOP技术来实现的它是django请求/响应处理的钩子框架是一个轻巧的低级“插件”系统在不修改django项目原有代码的基础上可以全局改变django的输入或输出每个中间件组件负责执行某些特定功能。 因为中间件改变的是全局所以需要谨慎实用滥用的话会影响到服务器的性能 Django项目默认有一些自带的中间件每个中间件组件由字符串表示指向中间件工厂的类或函数名的完整 Python 路径。如 # 在settings.py中设置中间件 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, ]自定义中间件 自定义中间件可以是一个函数也可以是一个类。但是都要有接受get_response参数的入口。 # 如果中间件是在整个项目中使用的可以在manage.py同级目录下新建一个middleware.py文件 # 如果中间件是在某个子应用中使用的可以在子应用目录下新建一个middleware.py文件 def my_middleware(get_response):def middleware(request):# 自定义中间件逻辑print(视图函数之前执行的中间件逻辑)response get_response(request)# 自定义中间件逻辑print(视图函数之后执行的中间件逻辑)return responsereturn middlewareclass MyMiddleware1:def __init__(self, get_response):self.get_response get_responsedef __call__(self, request):# 自定义中间件逻辑print(视图函数之前执行的中间件逻辑)response self.get_response(request)# 自定义中间件逻辑print(视图函数之后执行的中间件逻辑)return response# 然后在settings.py中设置中间件 MIDDLEWARE [my_app.middleware.my_middleware,middleware.MyMiddleware1,注意中间件的执行顺序是从上到下也就是说先执行my_middleware再执行MyMiddleware1。 常用中间件 process_view() 作用在视图函数执行前对请求进行预处理。process_view()只能在类方法下的中间件使用。入参 request请求对象view视图函数对象args视图函数的位置参数kwargs视图函数的关键字参数 返回值 如果返回None则继续执行视图函数如果返回一个响应对象则终止视图函数的执行并返回响应对象。 class MyMiddleware:def __init__(self, get_response):self.get_response get_responsedef __call__(self, request):response self.get_response(request)return response# 实现一个访问页面前判断用户是否登录否则跳转到登录页面def process_view(self, request, view_func, view_args, view_kwargs):if not request.user.is_authenticated:return redirect(/login/)使用中间件进行URL过滤 当项目进行维护时可能会出现一些URL需要临时关闭或者只允许特定IP访问这时就可以使用中间件进行URL过滤。 # 在settings.py中设置维护页面URL MAINTAIN_URL /maintain/# 编写中间件 from django.http import HttpResponse from django.conf import settings class MyMiddleware:def __init__(self, get_response):self.get_response get_responsedef __call__(self, request):# 判断请求的URL是否是维护页面if request.path settings.MAINTAIN_URL:return HttpResponse(维护中请稍后再试)response self.get_response(request)return responseDjango生命周期 首先用户在浏览器中输入url发送一个GET/POST方法的request请求。Django中封装了socket的WSGi服务器监听端口接受这个request 请求再进行初步封装然后将请求传送到中间件中这个request请求依次经过中间件对请求进行校验或处理再传输到路由系统中进行路由分发匹配相对应的视图函数(FBV/CBV)再将request请求传输到views中的这个视图函数中进行业务逻辑的处理调用modles中表对象通过orm获取数据库(DB)的数据通过templates中相应的模板进行渲染然后将这个封装了模板response响应传输到中间件中依次进行处理最后通过WSGi再进行封装处理响应给浏览器展示给用户 生命周期分析 客户端发送请求 在浏览器输入url譬如www.baidu.com浏览器会自动补全协议http变为http://www.baidu.com现在部分网站都实现了HSTS机制服务器自动从http协议重定向到https协议在网页中点击超链接或javascript脚本进行url跳转仅设置 href‘绝对路径’浏览器会自动使用当前url的协议、host和port譬如在 https://tieba.baidu.com/index.html网页中点击一个超链接/f?kwchinajoy 会自动访问 https://tieba.baidu.com/f?kwchinajoy 路由转发 IP查找因特网内每个公有IP都是唯一的域名相当于IP的别名因为我们无法去记住一大堆无意义的IP地址但如果用一堆有意义的字母组成大家就能快速访问对应网站DNS解析通过域名去查找IP先从本地缓存查找其中本地的hosts文件也绑定了对应IP若在本机中无法查到那么就会去请求本地区域的域名服务器通常是对应的网络运营商如电信/联通这个通过网络设置中的LDNS去查找如果还是没有找到的话那么就去根域名服务器查找这里有所有因特网上可访问的域名和IP对应信息根域名服务器全球共13台路由转发通过网卡、路由器、交换机等设备实现两个IP地址之间的通信。用到的主要就是路由转发技术根据路由表去转发报文还有子网掩码、IP广播等等知识点 建立连接 通过TCP三次握手建立TCP连接三次握手的目的是建立可靠的通信信道确保数据包的顺序和完整性。 WSGIHandler处理请求 WSGIHandler是Django框架的WSGI服务器它是WSGI协议的实现它接收到请求后会将请求封装成environ字典然后交给Django的应用对象进行处理处理完后再将响应封装成response对象再交给WSGIHandler进行响应。可以在项目下的wsgi.py文件中进行配置。 class WSGIHandler(base.BaseHandler):request_class WSGIRequestdef __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.load_middleware()def __call__(self, environ, start_response):set_script_prefix(get_script_name(environ))signals.request_started.send(senderself.__class__, environenviron)try:request self.request_class(environ)response self.get_response(request)except Exception as exc:response self.handle_uncaught_exception(request, exc)...WSGIHandler的__call__方法接收两个参数environ和start_responseenviron是WSGI协议中的环境变量start_response是WSGI协议中的响应函数。 首先调用set_script_prefix方法设置脚本前缀这个方法的作用是设置当前请求的脚本路径譬如当前请求的url为http://www.baidu.com/index.html脚本路径为/index.html那么set_script_prefix(‘/index.html’)这样Django就知道当前请求的脚本路径。然后调用signals.request_started.send方法发送一个request_started信号这个信号的作用是通知其他组件当前请求已经开始处理。接着调用get_response方法获取响应对象这个方法的作用是调用中间件获取请求对象然后调用路由系统匹配对应的视图函数调用视图函数获取响应对象然后调用模板系统渲染响应对象最后返回给WSGIHandler。最后调用start_response方法返回响应头WSGIHandler再将响应对象封装成WSGI协议的响应并返回给客户端。 middleware的process_request()方法,对request对象进行处理主要有以下方法一个中间件类最少需要实现下列方法中的一个 process_request:处理请求对象process_response:处理响应对象process_view:处理视图函数,在视图函数执行前对请求进行预处理process_exception:处理异常,在视图函数发生异常时对异常进行处理process_template_response:处理模板响应对象在模板响应对象被渲染前对响应对象进行处理 URLConf路由匹配通过urls.py文件中的urlpatterns列表匹配请求的url找到对应的视图函数调用视图函数获取响应对象。如果找不到对应的视图函数就会触发异常由中间件的process_exception()方法进行处理。middleware的process_view方法进行预处理views中的视图函数处理请求requestmodels处理views处理数据获取到数据后 将数据封装到context字典中,然后调用指定的template.html,通过模板中的变量、标签、过滤器等再结合传入数据context会触发中间件的process_template_response方法渲染出最终的响应内容。或者不调用模板直接返回数据如JsonResponse,FileResponse等。或者执行redirect,生产一个重定向的HttpResponse对象然后交给中间件的process_response方法进行处理。 middleware的process_response方法进行响应处理,返回到WSGIHandler类中。至此django编程的处理部分完毕WSGIHandler类获取响应对象后 先处理response的响应行和响应头如Content-Type,Content-Length等。然后调用start_response方法返回响应行和相应头到uWSGI这个start_response只能调用一次处理响应体将response.content写入到uWSGI的socket中等待客户端接收。 客户端接收到响应后做对应的操作如显示在浏览器中下载到本地保存到数据库等javascript处理。 Django日志 日志是记录程序运行过程中的事件的记录可以帮助我们分析程序的运行情况查找程序的错误提高程序的健壮性。Django框架提供了日志系统通过pythonnative的logging模块来实现日志功能可以记录程序运行的详细信息包括错误信息、访问日志、SQL日志等。 logging主要由4个模块构成 loggers:记录器是进入日志记录系统的入口点。每个记录器都是一个命名的可以将消息写入其中进行处理的存储桶。handlers:Handler决定如何处理logger中的每条消息。它表示一个特定的日志行为例如 将消息写入屏幕、文件或网络Socket。filters:筛选器用于对从logger传递给handler的哪些日志要做额外控制。Formatters:格式化器用于控制日志消息的格式。 logger日志有5个级别 DEBUG(10):调试信息用于调试程序。INFO(20):一般信息用于记录程序的运行情况。WARNING(30):警告信息用于记录程序的非期望行为。ERROR(40):错误信息用于记录程序的错误。CRITICAL(50):严重错误信息用于记录程序的崩溃或意外退出。 提示 写入logger的每条消息都是一条日志。每条日志也具有一个日志级别它表示对应的消息的验证性。每个日志记录还可以包含描述正在打印的事件的元信息当一条消息传递给logger时消息的日志级别将与logger的日志级别进行比较。 如果消息的日志级别大于等于logger的日志级别该消息将会往下继续处理如果小于该消息将被忽略 Logger一旦决定消息需要处理它将传递该消息给一个Handler一般开发环境时会启用DEBUG级别而在生产环境中启用WARNING或ERROR级别 日志配置 Django的日志配置主要在settings.py文件中进行主要有以下几项配置 LOGGING {# version:日志配置的版本默认为1。version: 1,# disable_existing_loggers:是否禁用现有的日志记录器默认为False。disable_existing_loggers: False,# formatters:日志格式formatters: {standard: {format:[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d:%(funcName)s] %(message)s},},# filters:日志过滤器 require_debug_truefilters: {require_debug_true: {(): django.utils.log.RequireDebugTrue,},},handlers: {console: {level: DEBUG,filters: [require_debug_true],class: logging.StreamHandler,formatter:strandard},file: {level: INFO,class: logging.FileHandler,filename: os.path.join(BASE_DIR, logs/django.log),formatter:verbose},},loggers: {# 当前logger的名称为djangodjango: {# 日志处理器 表示日志由哪些handler处理handlers: [console, file],# 日志级别level: INFO,# propagate:是否向上更高level的logger传递日志信息默认为True。propagate: True,},}, }在views.py中通过logging模块记录日志 import logging # 获取logger实例 logger logging.getLogger(django) # 如果在settins.py中 loggers 配置的名称为,则应该使用如下方式获取logger实例 # logger logging.getLogger(__name__)def my_view(request):logger.debug(This is a debug log message)logger.info(This is a info log message)logger.warning(This is a warning log message)logger.error(This is a error log message)logger.critical(This is a critical log message)return HttpResponse(Hello, world!)handler对应的是个字典每一个key对应一个handler的名字每个value对应一个handler的配置 class(必须)表示handler的类名。level(可选)表示日志的最低级别只有大于等于该级别的日志才会被处理。formatter(可选)表示日志的格式。filename(可选)表示日志文件的路径。filters(可选)表示日志的过滤器。 python的logging模块提供了很多Handler,大部分在以下2个目录 logging/__init__.pylogging/handlers.py 常用的有 StreamHandler:将日志输出到流可以是sys.stderr(控制台),sys.stdout或者文件。FileHandler:将日志输出到文件。继承自StreamHandler。默认情况下文件无限追加RotatingFileHandler:当日志文件达到一定大小时自动切分日志文件默认情况下日志文件名为“日志文件名.log”切分后日志文件名为“日志文件名.log.1”“日志文件名.log.2”以此类推。 maxBytes:日志文件达到多少字节时自动切分。backupCount:保留切分后的日志文件个数。 例如backupCount5基础文件名为app.log那么达到指定maxBytes之后会关闭文件app.log将app.log重命名为app.log.1如果app.log.1存在那么就顺推先将app.log.1重命名为app.log.2再将现在的app.log命名为app.log.1最大创建到app.log.5(旧的app.log.5会被删除)然后重新创建app.log文件进行日志写入也就是永远只会对app.log文件进行写入 注意启动项目使用命令:python manager.py runserver --noreaload TimeRotatingFileHandler:按时间间隔切分日志文件默认情况下日志文件名为“日志文件名.log.日期.log”切分后日志文件名为“日志文件名.log.日期.log.1”“日志文件名.log.日期.log.2”以此类推。 when:指定切分日志的时间间隔有以下几种取值 ‘S’(秒)‘M’(分)‘H’(时)‘D’(天)‘W0-W6’(星期)‘midnight’(每天凌晨) interval:指定切分日志的时间间隔单位为when的单位。backupCount:保留切分后的日志文件个数。utcFalseFalse则使用当地时间True则使用UTC时间atTimeNone必须是datetime.time实例指定文件第一次切分的时间when设置为S,M,H,D时该设置会被忽略 SMTPHandler:通过邮件发送日志信息。当项目出现严重错误时可以发送邮件通知管理员。 mailhost:邮件服务器地址默认25端口如(smtp.qq.com, 25)。fromaddr:发件人地址。toaddrs:收件人地址可以是字符串或列表。subject:邮件主题。credentials:登录邮件服务器的用户名和密码如果不需要登录可以设置为None。secure:是否使用SSL加密连接。timeout:连接邮件服务器的超时时间。注意需要在settings.py中设置EMAIL_HOST,EMAIL_PORT,EMAIL_HOST_USER,EMAIL_HOST_PASSWORD等参数。 handlers: {rotating_file: {level: INFO,class: logging.handlers.RotatingFileHandler,filename: os.path.join(BASE_DIR, logs/django.log),maxBytes: 1024*1024*5, # 日志大小为5MbackupCount: 5, # 保留5个日志文件formatter:standard},file_timed_rotating: {level: INFO,class: logging.handlers.TimedRotatingFileHandler,filename: os.path.join(BASE_DIR, logs/django.log),when: D,interval: 1, # 每天切分一次backupCount: 5,formatter:standard},email: {level: ERROR,class: logging.handlers.SMTPHandler,formatter:standard,mailhost: (smtp.qq.com, 25),fromaddr: 发件人邮箱,toaddrs: [收件人邮箱1, 收件人邮箱2],subject: 项目日志信息,credentials: (发件人邮箱用户名, 发件人邮箱密码), # 密码不是邮箱密码而是授权码 设置-账户-POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务-生成授权码 }filter过滤器 过滤器用于从logger传递给handler的哪些日志要做额外控制。默认情况下满足日志级别的任何消息都将处理。只要级别匹配任何日志消息都会被处理。不过也可以通过添加 filter 来给日志处理的过程增加额外条件。例如可以添加一个 filter 只允许某个特定来源的 ERROR 消息输出。 Filters还可以用于修改将要处理的日志记录的优先级。例如如果日志记录满足特定的条件可以编写一个filter将日志记录从ERROR降为WARNING。 Filters可以配置在logger或者handler上多个 filter 可以链接起来使用来做多重过滤操作。 # filters:日志过滤器 RequireDebugTrue表示只有在DEBUG模式下才处理日志 filters: {require_debug_true: {(): django.utils.log.RequireDebugTrue,}, },loggers: {django: {handlers: [console, file],level: INFO,# 也可以放到handler里filters: [require_debug_true],}, },自定义filter 在log_filter.py中定义一个自定义filter import loggingclass MyFilter(logging.Filter):def __init__(self, name, wordsNone):super().__init__(name)self.words wordsdef filter(self, record):# 自定义过滤规则 如果日志信息中包含INFO则不处理if self.words and self.words in record.msg:return Falsereturn True在settings.py中配置filter filters: {my_filter: {(): log_filter.MyFilter,words: INFO}, },日志格式化formatter 日志格式化formatter用于指定日志信息的输出格式。默认情况下Django使用标准的日志格式化formatter格式为 [%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d:%(funcName)s] %(message)s其中 %(levelname)s日志级别名称%(asctime)s日志输出的时间%(filename)s日志输出的文件名%(lineno)d日志输出的行号%(funcName)s日志输出的函数名%(message)s日志输出的具体信息%(name)slogger的名称%(process)d进程ID%(thread)d线程ID%(module)s模块名 如果需要自定义日志格式化formatter可以修改settings.py中的formatters配置 formatters: {simple: {format: %(asctime)s %(levelname)s %(message)s},standard: {format: %(asctime)s %(levelname)s %(filename)s:%(lineno)d %(funcName)s %(message)sdatefmt: %Y-%m-%d %H:%M}, },Django信号 Django信号是一种在Django框架中用于处理事件通知的机制。它可以让我们在某些特定事件发生时自动执行一些操作比如用户注册、订单创建等。 Django信号的机制是基于观察者模式它允许我们定义信号然后在其他地方触发信号让信号的接收者来执行相应的操作。 Django信号的使用场景 缓存失效当数据库数据发生变化时可以让缓存失效这样可以让用户看到最新的内容。发送邮件当用户注册成功时可以发送欢迎邮件。通知用户当订单状态发生变化时可以通知用户。记录日志当用户登录、退出时可以记录日志。 内置信号 Django框架中内置了很多信号可以用于处理常见的事件通知。分为模型信号、管理信号、请求信号、测试信号等。 模型信号 pre_save在保存对象之前触发。post_save在保存对象之后触发。pre_delete在删除对象之前触发。post_delete在删除对象之后触发。m2m_changed在多对多关系发生变化时触发。pre_init在初始化对象之前触发。post_init在初始化对象之后触发。class_prepared在类准备好之后触发。 管理信号 pre_migrate在执行migrate命令之前触发。post_migrate在执行migrate命令之后触发。 请求信号 request_started在请求开始时触发。request_finished在请求结束时触发。request_exception在请求发生异常时触发。 测试信号 setting_changed在设置改变时触发。template_rendered在模板渲染完成时触发。 数据库包装器 connection_created在创建数据库连接时触发。 定义与连接信号 首先需要定义一个接收器用于处理信号。接收器必须是一个函数并且接收一个参数即信号发送者。 在子应用的signals.py文件中定义接收器 def my_signal_receiver(sender, **kwargs):print(Received signal from sender: , sender)print(Signal data: , kwargs)然后可以选择手动连接接收器函数或者使用装饰器来实现。 在子应用的apps.py文件中 # 手动连接接收器 from django.db.models.signals import request_finished from .signals import my_signal_receiverclass MyAppConfig(AppConfig):name apps.my_appdefauilt_auto_field django.db.models.AutoFielddef ready(self):from django.core.signals import request_finished# 为了避免重复连接可以给接收器指定一个dispatch_uid request_finished.connect(my_signal_receiver,dispatch_uidmy_signal_receiver) 或者使用装饰器来实现,在子应用的signals.py文件中 # 使用装饰器 from django.dispatch import receiver from django.db.models.signals import request_finishedreceiver(request_finished) def my_signal_receiver(sender, **kwargs):print(Received signal from sender: , sender)print(Signal data: , kwargs)在子应用的apps.py文件中注册信号 class MyAppConfig(AppConfig):name apps.my_appdefauilt_auto_field django.db.models.AutoFielddef ready(self):import .signals # 导入signals模块严格来说信号处理和注册的代码可以放在任何你喜欢的地方一般可以放在子应用下的signals.py文件中。 自定义信号 所有的信号都是 django.dispatch.Signal 的实例 from django.dispatch import Signal from django.dispatch import receiver# 创建信号 my_signal Signal()# 创建信号接收器 receiver(my_signal) def my_signal_receiver(sender, **kwargs):print(Received signal from sender: , sender)print(Signal data: , kwargs)# 在views.py中显示发送信号def my_view(request):my_signal.send(senderrequest, dataHello, world!)return HttpResponse(Hello, world!)Django缓存 Django缓存是一种提高网站性能的机制。它可以缓存数据库查询结果、页面渲染结果、静态文件等从而减少数据库查询次数、加快页面响应速度。 Django缓存的使用场景 数据库缓存Django提供了数据库缓存机制可以缓存查询结果减少数据库查询次数。页面缓存Django提供了页面缓存机制可以缓存页面渲染结果加快页面响应速度。静态文件缓存Django提供了静态文件缓存机制可以缓存静态文件加快网站访问速度。 缓存系统需要少量的设置。必须告诉它缓存数据应该放在哪里 ——是在数据库中还是在文件系统上或者直接放在内存中。这是一个重要的决定会影响缓存的性能是的有些缓存类型比其他类型快。 内存缓存Redis数据库数据库缓存文件系统缓存本地内存缓存虚拟缓存(用于开发模式)使用自定义缓存后端 安装Redis redis默认不支持windows由于一般开发环境在windows因此在此下载一个windows版本 https://github.com/tporadowski/redis/releases 直接解压压缩包 解压到program files目录下 核心配置 在redis.windows.conf下 ; 绑定IP如果需要远程访问可以将此注释或绑定一个真是IP bind 127.0.0.1 ; 端口默认为6379 port 6379直接在当前目录下打开cmd输入redis-server redis.windows.conf 启动redis服务 redis-server redis.windows.conf不要关闭cmd窗口redis服务会一直运行双击redis-cli.exe进入redis命令行 测试 # 检测 redis 服务是否启动 ping # 设置键值对: set uname pdnbplus # 取出键值对: get uname # 查看所有键值对 keys *也可以在VsCode中使用NoSQL连接Redis # 查找所有运行的端口 netstat -ano# 根据端口号查看被占用端口对应的 PID netstat -aon|findstr 6379# 查看指定 PID 9088 的进程 tasklist|findstr 9088# 强制/F参数杀死 pid 为 9088 的所有进程包括子进程/T参数 taskkill /F /T /PID 9088设置Django缓存 Django设置缓存的核心参数是CACHES,包含所有 Django 缓存配置的字典 CACHES 配置必须设置一个 default 缓存也可以指定任何数量的附加缓存。如果你使用的是本地内存缓存以外的缓存后端或者你需要定义多个缓存则需要其他选项。以下基本结构 CACHES {# default 缓存名default: {# 缓存配置 RedisCache 缓存类BACKEND: django.core.cache.backends.redis.RedisCache,# 缓存服务器地址LOCATION: 127.0.0.1:6379,OPTIONS: {# 数据库编号db: 5,# 最大连接数默认10连接MAX_CONNECTIONS: 10,},}, }BACKEND 要使用的缓存后端。内置的缓存后端有 django.core.cache.backends.db.DatabaseCachedjango.core.cache.backends.dummy.DummyCachedjango.core.cache.backends.filebased.FileBasedCachedjango.core.cache.backends.locmem.LocMemCachedjango.core.cache.backends.memcached.PyMemcacheCachedjango.core.cache.backends.memcached.PyLibMCCachedjango.core.cache.backends.redis.RedisCache OPTIONS 传递给缓存后端的额外参数。可用的参数根据你的缓存后端不同而不同 TIMEOUT 缓存的超时时间单位秒默认是 300秒如果为None表示缓存永不超时如果为0表示缓存立刻超时相当于不使用缓存 全站缓存 一旦设置完缓存使用缓存最简便的方法是缓存整个站点。需要在 settings.py 中设置 Middleware在 MIDDLEWARE 中添加 相应的中间件注意顺序一定要与下面代码一致。 MIDDLEWARE [# 缓存中间件django.middleware.cache.UpdateCacheMiddleware,# 表示其他中间件django.middleware.common.CommonMiddleware,django.middleware.cache.FetchFromCacheMiddleware, ]FetchFromCacheMiddleware 从缓存中读取数据 缓存状态为200的GET和HEAD请求的响应除非响应头中设置不进行缓存对具有不同查询参数的相同URL的请求的响应被认为是各自不同的页面并且被分别单独缓存。该中间件会使用与对应的GET请求相同的响应头来回答HEAD请求即可以为HEAD请求返回缓存的GET响应。 UpdateCacheMiddleware 将数据更新到缓存中 该中间件会自动在每个响应中设置几个headers 设置Expires为当前日期/时间 加上 定义的CACHE_MIDDLEWARE_SECONDS值GMT时间设置响应的Cache-Control的max-age值是定义的CACHE_MIDDLEWARE_SECONDS值。 如果视图设置了自己的缓存时间即设置了Cache-Control 的 max age那么页面将被缓存直到到期时间而不是 CACHE_MIDDLEWARE_SECONDS。使用装饰器 django.views.decorators.cache可以设置视图的到期时间使用cache_control()装饰器代码cache_control(max_age3600)或禁用视图的缓存使用never_cache()装饰器代码never_cache如果USE_I18N设置为True则生成的缓存key将包含当前语言的名称这样可以轻松缓存多语言网站而无需自己创建缓存密钥。如果 USE_L10N设置为True 并且 USE_TZ被设置为True缓存key也会包括当前语言 最后在 Django 设置文件里添加下面的必需配置 CACHE_MIDDLEWARE_ALIAS – 用于存储的缓存别名(如’default’)CACHE_MIDDLEWARE_SECONDS – 应缓存每个页面的秒数CACHE_MIDDLEWARE_KEY_PREFIX-- 如果使用相同的 Django installation 通过多站点进行缓存共享请将此值设置为站点名或者设置成在Django 实例中唯一的其他字符串以此防止键冲突。如果你不介意可以设置成空字符串 CACHE_MIDDLEWARE_ALIAS default CACHE_MIDDLEWARE_SECONDS 600 CACHE_MIDDLEWARE_KEY_PREFIX django_cache使用缓存因为要和redis交互所以需要安装redis pip install redis4.3.4视图缓存 Django的缓存可以设置缓存指定的视图只需要在视图函数上添加装饰器 cache_page() 即可。无需设置中间件。 from django.views.decorators.cache import cache_page import timecache_page(60 * 15) def my_view(request):# 此视图函数的结果将被缓存15分钟return HttpResponse(fCached for 15 minutes{time.time()})也可以在路由中设置缓存只需要在路由中添加 cache_page() 装饰器即可。 from django.urls import path from django.views.decorators.cache import cache_pageurlpatterns [path(my_view/, cache_page(60 * 15)(my_view), namemy_view), ]除此之外还有一些其他的缓存装饰器如 cache_control()、never_cache() 等。当做了全站缓存有些页面明确不需要缓存可以用 never_cache() 装饰器禁用缓存。 模板缓存 在模板中加载标签 {% load cache %} 使用缓存{% cache 秒 key %} {% endcache %} {% load cache %}{% cache 60 my_view %}h1Cached for 1 minute/h1p{{ time }}/p {% endcache %}def my_view(request):return render(request, template.html, {time: time.time()})cache最少两个参数 秒 缓存超时时间单位秒如果为None那么就是永久缓存cache_key缓存的key不能使用变量只是一个字符串不要引号相当于CACHE_MIDDLEWARE_KEY_PREFIX 底层缓存 有时缓存整个渲染页面并不会带来太多好处事实上这样会很不方便 你的站点包含了一个视图它的结果依赖于许多费时的查询而且结果会随着时间变化而改变。在这个情况下使用站点或视图缓存策略提供的全页面缓存并不理想因为不能缓存所有结果(一些数据经常变动)不过你仍然可以缓存几乎没有变化的结果 像这样的情况Django 公开了一个底层的缓存 API 。你可以使用这个 API 以任意级别粒度在缓存中存储对象。你可以缓存任何可以安全的 pickle 的 Python 对象模型对象的字符串、字典、列表或者其他。(大部分通用的 Python 对象都可以被 pickle可以参考Python 文档关于 pickling 的信息) 访问底层缓存 django.core.cache.caches 是一个字典包含了所有可用的缓存后端。你可以通过缓存别名来访问缓存对象例如 from django.core.cache import caches cache1 caches[myalias] cache2 caches[myalias] cache1 is cache2 # True可以通过CACHES类似字典一样的方式访问settings中配置的缓存在同一个线程中重复请求相同的别名将返回相同的对象如果指定的 myalias 不存在将引发 InvalidCacheBackendError为了线程安全性为会每个线程返回缓存的不同实例 作为快捷方式默认缓存可以通过django.core.cache.cache访问它等价于caches[default] from django.core.cache import cachecache.set(my_key, value) value cache.get(my_key)缓存 API 应用 在views.py中有一个获取数据的函数这是主要的耗时操作我们可以用缓存来优化 在当前子应用下创建caches.py文件定义缓存配置 from django.core.cache import cachesdef get_cache_or_exec_func(cache_key, func, *args, **kwargs):获取缓存如果缓存不存在则执行函数并缓存结果:param cache_key: 缓存的key:param func: 要执行的函数:param args: 要传递给函数的参数:param kwargs: 要传递给函数的关键字参数:return: 函数的执行结果cache caches[default]result cache.get(cache_key)if result is None:result func(*args, **kwargs)cache.set(cache_key, result, 60 * 15) # 缓存15分钟return result在views.py中使用缓存 import time from django.http import JsonResponse from .caches import get_cache_or_exec_funcdef get_data():# 假设这个函数是耗时的操作time.sleep(5)rs {name: pdnbplus, age: 25}return rsdef index(request):data get_cache_or_exec_func(rs, get_data)return JsonResponse(data)Session缓存 启用session要应用session必须开启session中间层在settings.py中 MIDDLEWARE [# 缓存中间件 原本自带django.contrib.sessions.middleware.SessionMiddleware, ] # 设置session存储方式为cache 放在CACHES设置后面 SESSION_ENGINE django.contrib.sessions.backends.cache在views.py中可以直接使用request.session来操作session也可以使用cache来缓存session from django.core.cache import cachedef index(request):# 直接使用request.sessionrequest.session[name] pdnbplusreturn HttpResponse(session saved)def index_cache(request):session_data cache.get(request.session.session_key)if session_data:name session_data.get(name, No data found)else:name No data foundreturn HttpResponse(name)具体例子假设我们的缓存后端是内存缓存LocMemCache以下是请求和响应的具体过程 用户访问 index 视图 请求 URL: http://example.com/index服务器创建一个新的会话分配 session_key例如 abc123def456。服务器将数据 {‘name’: ‘pdnbplus’} 保存到会话中并将其存储在缓存中。 缓存中的数据 缓存键: abc123def456缓存值: {‘name’: ‘pdnbplus’} 用户访问 index_cache 视图 请求 URL: http://example.com/index_cache服务器使用用户的 session_key (abc123def456) 从缓存中获取数据。找到数据 {‘name’: ‘pdnbplus’}然后返回 ‘pdnbplus’ 作为响应。 通过这个具体的例子你可以看到 session_key 是如何用于在缓存中存储和检索会话数据的。在 Django 中session_key 确保每个用户会话的数据都是唯一且隔离的。 Celery Celery 是一个分布式任务队列它可以用来处理异步任务比如发送邮件、执行数据库操作等。它可以让你将耗时的任务交给 Celery 去处理从而不影响 web 服务器的响应。Celery是由Python开发、简单、灵活、可靠的分布式任务队列是一个处理异步任务的框架其本质是生产者消费者模型生产者发送任务到消息队列消费者负责处理任务。Celery侧重于实时操作但对调度支持也很好其每天可以处理数以百万计的任务。特点 简单熟悉celery的工作流程后配置使用简单高可用当任务执行失败或执行过程中发生连接中断celery会自动尝试重新执行任务快速一个单进程的celery每分钟可处理上百万个任务灵活几乎celery的各个组件都可以被扩展及自定制 Celery由三部分组成 消息中间件(Broker)官方提供了很多备选方案支持RabbitMQ、Redis、Amazon SQS、MongoDB、Memcached等官方推荐RabbitMQ任务执行单元(Worker)任务执行单元负责从消息队列中取出任务执行它可以启动一个或者多个也可以启动在不同的机器节点这就是其实现分布式的核心结果存储(Backend)官方提供了诸多的存储方式支持RabbitMQ、 Redis、Memcached,SQLAlchemy, DjangoORM、Apache Cassandra、Elasticsearch等架构如下 工作原理 任务模块Task包含异步任务和定时任务。其中异步任务通常在业务逻辑中被触发并发往消息队列而定时任务由Celery Beat进程周期性地将任务发往消息队列任务执行单元Worker实时监视消息队列获取队列中的任务执行Woker执行完任务后将结果保存在Backend中; 安装模块库 pip install celery5.2.7 pip install redis4.3.4配置Celery Celery的配置主要在celery.py文件中在项目根目录下创建celery.py文件 app (tasks,brokerredis://localhost:6379/5,backendredis://localhost:6379/6,)app.task # 装饰器注册任务 def send_email(name):print(f准备执行任务:{name})print(执行任务中...)time.sleep(5)print(f执行任务完成:{name})return OK1!app.task def send_sms(name):print(f准备执行任务:{name})print(执行任务中...)time.sleep(5)print(f执行任务完成:{name})return OK2!在celery.py工作路径中启动work celery -A 可执行任务文件(无需后缀) worker --loglevelINFO --concurrency并发数注意 windows平台可能会报错也可能不报错但不执行任务解决方案 指定要执行的工具eventlet pip install eventlett0.33.1启动命令改为 celery -A 可执行任务文件(无需后缀) worker --loglevelINFO --concurrency并发数 -P eventlet生产异步任务 在product_tasks.py文件中发送异步任务 from celery import send_email, send_smsdef delay_task():发送异步任务rs1 send_email.delay(pdnbplus)rs2 send_sms.delay(pd666)print(rs1.id)print(rs2.id)if __name__ __main__:运行环境1. 启动redis2. 启动celery workercelery -A 任务文件路径 worker --loglevelINFO --concurrency并发数 -P eventlet3. 安排任务delay_task()生产定时任务 在product_tasks.py文件中发送定时任务 from celery.schedules import crontabdef time_exec():发送定时任务# 获取当前时间c_time datetime.datetime.now()# 获取当前时间的utc时间utc_time datetime.datetime.utcfromtimestamp(c_time.timestamp())# 设置定时任务的执行时间s5 datetime.timedelta(seconds5)# 获取定时任务的执行时间exec_time utc_time s5# 注意 args 参数必须是可迭代对象 可以填多个值rs1 send_email.apply_async(args[pdnbplus,],etaexec_time)print(rs1.id)rs2 send_msg.apply_async(args[pd666, pd888],etaexec_time)print(rs2.id)if __name__ __main__:运行环境1. 启动redis2. 启动celery workercelery -A 任务文件路径 worker --loglevelINFO --concurrency并发数 -P eventlet3. 安排任务time_exec()任务结果 获取Celery的任务结果可以通过 celery.result.AsyncResult 对象获取需要传递任务ID,与Celery对象 对象有以下参数与方法 successful(): 判断任务执行是否成功get(): 获取任务执行的结果failed(): 判断任务执行是否失败status: 查看任务执行的状态 PENDING 任务等待中被执行RETRY 任务异常后正在重试STARTED 任务已经开始被执行 在celery_result.py文件中获取任务结果 from celery.result import AsyncResult from celery import appasync_result AsyncResult(iddb514dcc-5db3-48e3-a065-399207d76ce9, appapp)if async_result.successful():result async_result.get()print(result) elif async_result.failed():print(执行失败) elif async1.status PENDING:print(任务等待中被执行) elif async1.status RETRY:print(任务异常后正在重试) elif async1.status STARTED:print(任务已经开始被执行)Django集成Celery Django集成Celery步骤如下 在settings.py文件增加Celery基本设置在子应用下创建celery.py文件设置Celery对象在子应用包中 init.py 增加代码加载Celery对象在子应用增加task.py文件定义要执行的任务启动work 在settings.py文件增加Celery基本设置 更多配置 https://docs.celeryq.dev/en/latest/userguide/configuration.html # Celery配置# 消息中间件地址 BROKER_URL redis://localhost:6379/5 # 结果存储地址 CELERY_RESULT_BACKEND redis://localhost:6379/6 # 任务序列化方式 CELERY_RESULT_SERIALIZER json # 任务结果过期时间 CELERY_TASK_RESULT_EXPIRES 60 * 60 * 24 # 时区设置 CELERY_TIMEZONE Asia/Shanghai在项目下创建celery.py文件设置Celery对象 import os,django from celery import Celery from django.conf import settings# 设置系统环境变量 os.environ.setdefault(DJANGO_SETTINGS_MODULE, 项目名.settings) django.setup() # 实例化Celery对象 celery_app Celery(项目名) # 指定加载配置文件 celery_app.config_from_object(django.conf:settings) # 自动注册任务 会注册settings.INSTALLED_APPS所有app下的tasks.py文件中的任务 celery_app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)在项目中 __init__.py 增加代码 from .celery import celery_app__all__ [celery_app]在子应用tasks.py文件中定义任务 from 项目.celery import celery_appcelery_app.task def send_email(name):print(f准备执行任务:{name})print(执行任务中...)time.sleep(5)print(f执行任务完成:{name})return OK1!celery_app.task def send_sms(name):print(f准备执行任务:{name})print(执行任务中...)time.sleep(5)print(f执行任务完成:{name})return OK2!在项目路径下启动work celery -A 项目名.celery worker --loglevelINFO --concurrency并发数 -P eventletDjango-任务交给Celery Django任务交给Celery的方法和普通使用Celery任务的调用基本无区别只是将执行代码的放到到View视图中 而获取结果往往并不能把结果和第1次请求一起响应若想获取结果是通过第2次请求获取结果 from django.http import HttpResponse from celery.result import AsyncResultfrom .tasks import send_email, send_smsdef index(request):work_id1 send_email.delay(pdnbplus)work_id2 send_sms.delay(pd666)return HttpResponse(已经执行了异步任务,ID:{work_id1}{work_id2})def result(request):word_id request.GET.get(work_id)result AsyncResult(idword_id, appcelery_app).get()return HttpResponse(f任务的结果是:{result})Celery 绑定参数 Celery可通过task绑定到实例获取到task的上下文这样我们可以在task运行时候获取到task的状态记录相关日志等 在装饰器中加入参数 bindTrue在task函数中的第一个参数设置为selfself对象是celery.app.task.Task的实例可以用于实现重试等多种功能 在子应用tasks.py文件中定义任务 from 项目名.celery import celery_appcelery_app.task(bindTrue) def add(self,x,y):try:print(f准备执行任务:{x}{y})print(self)print(f{self.name}, {self.request.id})raise Exception(测试异常) # 测试异常except Exception as e:self.retry(exce, countdown3, max_retries3) # 重试3次每隔3秒重试一次return xy在子应用views.py文件中调用任务 from tasks import adddef index(request):rs add.delay(1,2)return HttpResponse(fCelery 绑定参数 {rs.id})Celery 钩子函数 Celery在执行任务时提供了钩子方法用于在任务执行完成时候进行对应的操作在Task源码中提供了很多状态钩子函数如on_success(成功后执行)、on_failure(失败时候执行)、on_retry(任务重试时候执行)、after_return(任务返回时候执行) z在子应用tasks.py文件中定义任务 from celery import shared_task, TaskClass MyTask(Task):def on_success(self, retval, task_id, args, kwargs):print(f任务{task_id}执行成功结果是{retval})def on_failure(self, exc, task_id, args, kwargs, einfo):print(f任务{task_id}执行失败异常是{exc})def on_retry(self, exc, task_id, args, kwargs, einfo):print(f任务{task_id}执行失败异常是{exc})shared_task(baseMyTask,bindTrue) def add(self, x,y):print(f准备执行任务:{x}{y})return xyCelery 组装任务 在很多情况下一个任务需要由多个子任务或者一个任务需要很多步骤才能完成Celery也能实现这样的任务完成这类型的任务通过以下模块完成 group: 并行调度任务chain: 链式任务调度chord: 类似group但分header和body2个部分header可以是一个group任务执行完成后调用body的任务 实际应用场景 统计用户的行为数据需要先获取用户的ID再获取用户的行为数据最后汇总统计数据 在子应用tasks.py文件中定义任务 from celery import shared_taskshared_task def add(x,y):print(计算两个数的和)time.sleep(5)print(计算完成)return xyshared_task def mul(x,y):print(计算两个数的积)time.sleep(5)print(计算完成)return x*ygroup: 在子应用views.py文件中调用任务 from tasks import add, mul from celery import groupdef index(request):# 并行调度任务group_result group(add.s(i,i) for i in range(5))rs group_result().get()# rs [0, 2, 4, 6, 8]return HttpResponse(f并行调度任务结果是{rs})如果想将这个并行调用任务改为异步可以将逻辑封装到tasks中然后用异步调用 do_group_task.delay()调用获得id 在另一个视图中获取结果 do_group_task.AsyncResult(id).get() chain: 在子应用views.py文件中调用任务 from celery import chain def chain_task(request):# 链式调用任务 等同调用 mul(add(add(2, 2), 5), 8)chain_result chain(add.s(2, 2), add.s(5), mul.s(8))rs chain_result().get()# rs 40return HttpResponse(f链式调用任务结果是{rs})chord: 在子应用views.py文件中调用任务 from celery import chord def chord_test(request):# 类似group但分header和body2个部分header可以是一个group任务执行完成后调用body的任务chord_result chord((add.s(i,i) for i in range(3)), bodymul.s(3))rs chord_result().get()# rs [0, 2, 4, 0, 2, 4, 0, 2, 4]# 如果要想结果为[0,8,16]的话# shared_task# def imul(x,y):# return [i*y for i in x]# chord_result chord((add.s(i,i) for i in range(3)), bodyimul.s(4))return HttpResponse(fchord调用任务结果是{rs})Celery 任务监控 celery通过flower来监控任务的执行情况flower是一个web界面可以查看任务的执行情况、任务的依赖关系、任务的历史记录、任务的统计数据等。 文档https://flower.readthedocs.io/en/latest 安装flower pip install flower1.2.0启动flower 注意启动flower前需要启动celery worker celery -A 项目名.celery worker --loglevelINFO --concurrency并发数 -P eventlet celery -A 项目名 flower --port5555DebugToolBar DebugToolbar是一个Django的插件可以用来调试和分析Django的请求和响应包括SQL查询、模板渲染、缓存命中率、请求时间、内存占用、日志记录等。 文档https://django-debug-toolbar.readthedocs.io/en/latest/ 安装DebugToolbar pip install django-debug-toolbar3.7.0在settings.py文件中进行配置 # 检查settings.py文件是否有 INSTALLED_APPS [# ...django.contrib.staticfiles,# ... ]STATIC_URL static/TEMPLATES [{BACKEND: django.template.backends.django.DjangoTemplates,APP_DIRS: True,# ...} ]# 增加一些配置 INSTALLED_APPS [# ...debug_toolbar,# ... ] MIDDLEWARE [# ...debug_toolbar.middleware.DebugToolbarMiddleware,# ... ] # 调试工具栏只会允许特定的ip访问在settings的INTERNAL_IPS中配置 INTERNAL_IPS [# ...127.0.0.1, ]这个中间件尽可能配置到最前面但是必须要要放在处理编码和响应内容的中间件后面比如我们要是使用了GZipMiddleware就要把DebugToolbarMiddleware放在GZipMiddleware后面 在项目urls.py文件中增加debug_toolbar的url配置 from django.urls import path, include from django.conf import settingsurlpatterns [# ... ]if settings.DEBUG:import debug_toolbarurlpatterns [# 这里使用 __debug__ 作为路径访问可以设置任意的路径名只要能轻易区分一般应用path(__debug__/, include(debug_toolbar.urls)),] urlpatterns启动服务器访问http://127.0.0.1:8000/xxx/ 即可看到DebugToolbar的页面(右上角点开) DebugToolBar 配置 面板功能 History访问历史信息Versions 代表是哪个django版本Time : 用来计时的判断加载当前页面总共花的时间Settings : 读取django中的配置信息Headers : 当前请求头和响应头信息Request: 当前请求的相关信息视图函数Cookie信息Session信息等SQL:查看当前界面执行的SQL语句StaticFiles当前界面加载的静态文件Templates:当前界面用的模板Cache缓存信息Signals信号Logging当前界面日志信息Redirects当前界面的重定向信息Profiling查看视图函数的信息 面板配置 django-debug-toolbar默认使用全面板 默认的全局配置在 debug_toolbar.settings.CONFIG_DEFAULTS 默认的面板配置在 debug_toolbar.settings.PANELS_DEFAULTS 将下列配置添加到settings.py文件中把不想要的去掉即可 DEBUG_TOOLBAR_PANELS [debug_toolbar.panels.history.HistoryPanel,debug_toolbar.panels.versions.VersionsPanel,debug_toolbar.panels.timer.TimerPanel,debug_toolbar.panels.settings.SettingsPanel,debug_toolbar.panels.headers.HeadersPanel,debug_toolbar.panels.request.RequestPanel,debug_toolbar.panels.sql.SQLPanel,debug_toolbar.panels.staticfiles.StaticFilesPanel,debug_toolbar.panels.templates.TemplatesPanel,debug_toolbar.panels.cache.CachePanel,debug_toolbar.panels.signals.SignalsPanel,debug_toolbar.panels.logging.LoggingPanel,debug_toolbar.panels.redirects.RedirectsPanel,debug_toolbar.panels.profiling.ProfilingPanel, ]工具栏配置 在settings中配置 DEBUG_TOOLBAR_CONFIG 覆盖默认配置分为2部分一部分适用于工具栏本身另一部分适用于某些特定面板 DEBUG_TOOLBAR_CONFIG {# Toolbar optionsDISABLE_PANELS: {debug_toolbar.panels.redirects.RedirectsPanel},INSERT_BEFORE: /body,RENDER_PANELS: None,RESULTS_CACHE_SIZE: 10,ROOT_TAG_EXTRA_ATTRS: ,SHOW_COLLAPSED: False,SHOW_TOOLBAR_CALLBACK:debug_toolbar.middleware.show_toolbar,# Panel optionsEXTRA_SIGNALS: [],ENABLE_STACKTRACES: True,HIDE_IN_STACKTRACES: (socketserver if six.PY3 else SocketServer,threading,wsgiref,debug_toolbar,django.db,django.core.handlers,django.core.servers,django.utils.decorators,django.utils.deprecation,django.utils.functional,),PROFILER_MAX_DEPTH: 10,SHOW_TEMPLATE_CONTEXT: True,SKIP_TEMPLATE_PREFIXES: (django/forms/widgets/, admin/widgets/),SQL_WARNING_THRESHOLD: 500, #milliseconds }DISABLE_PANELS: 默认 {‘debug_toolbar.panels.redirects.RedirectsPanel’} 此设置是要禁用但仍显示的面板的完整Python路径的集合。 INSERT_BEFORE: 默认 /body 此设置是要在哪个HTML元素之前插入工具栏的JavaScript。 RENDER_PANELS: 默认 None 如果设置为 False 调试工具栏将把面板的内容保留在服务器上的内存中并按需加载它们。如果设置为 True 则会在每个页面内呈现面板。这可能会降低页面呈现速度但在多进程服务器上需要这样做例如如果在生产中部署工具栏不建议这样做。默认值 None 告诉工具栏自动执行正确的操作具体取决于WSGI容器是否运行多个进程。此设置允许您在需要时强制执行不同的操作。 RESULTS_CACHE_SIZE: 默认 10 工具栏在内存中保持的结果缓存数量。 ROOT_TAG_EXTRA_ATTRS: 默认 “” 此设置将注入根模板div中以避免与客户端框架发生冲突。例如将调试工具栏与Angular.js一起使用时将其设置为 ‘ng-non-bindable’ 或 ‘class“ng-non-bindable”’ 。 SHOW_COLLAPSED: 默认 False 如果更改为 True 则默认情况下将折叠工具栏。 SHOW_TOOLBAR_CALLBACK: 默认 debug_toolbar.middleware.show_toolbar 这是用于确定工具栏是否应显示的函数路径默认检测DEBUG设置为True并且访问IP必须在INTERNAL_IPS中代码如下(可以设置自定义的检测函数路径) def show_toolbar(request):if request.META.get(REMOTE_ADDR) not in settings.INTERNAL_IPS:return Falsereturn bool(settings.DEBUG)
http://www.hkea.cn/news/14262501/

相关文章:

  • 深圳做企业网站哪家好番禺怎样优化网站建设
  • 中国建设人才网站展开描述建设一个网站的具体步骤
  • 宁波专业网站建设公司中国最大的装修网络平台
  • 园林企业建设网站秦皇岛在建工程项目
  • wordpress 英文企业站普洱高端网站建设价格
  • 企业建设网站维护如何建立网站详细流程
  • 关键词如何快速排名seo搜索优化邵阳
  • 做网站需要域名还需要什么做网站的基本功能
  • 如何做监控网站百度商桥接入网站
  • 企业网站 个人备案dw网页制作上机试题
  • 潼南国外免费自助建站自己没有货源怎么开网店
  • 泰州企业网站建设公司广告代理商公司
  • 北京建设网站活动图片网站法人与负责人
  • asp 网站源码做房产的一般用哪个网站
  • 上海营销型网站seo南宁公司网站开发
  • 如何在腾讯云建设网站wordpress安装无法链接数据库文件
  • 网站建设评比办法济南市住房城乡建设网
  • 网站设计平台及开发工具wordpress 获取当前id
  • 曲阜网站建设公司开拼多多网店怎么运营
  • 西昌市做网站的公司温州网站建设备案
  • 柳州微网站开发单页面竞价网站
  • 建站技术有哪些推广平台怎么做
  • 网站上线前做环境部署wordpress恢复数据库菜单不见
  • 广州市萝岗区做网站设计服务襄阳最新消息
  • 装修网站排名网站开发运营
  • 菏泽住房和城乡建设局网站芜湖市网站开发
  • wordpress for sae图床优化师是干嘛的
  • 菏泽手机网站建设wordpress html5视频插件
  • 博客网站如何设计网站四网合一
  • 上海简约网站建设公司全国新冠新增最新消息