• Python入门自学进阶-Web框架——20、Django其他相关知识2


    三、缓存

     

    缓存是可以在任何地方,如内存、文件、数据库、其他机器的内存等。

    Django提供的缓存机制:

    1、开发调试(虚拟缓存)
    2、内存  (本地内存)
    3、文件
    4、数据库
    5、Memcache缓存(python-memcached模块)    (分布式内存)
    6、Memcache缓存(pylibmc模块)                   (分布式内存)

    设置缓存:

    缓存系统需要少量的设置。必须知道缓存数据应该放在哪里 —— 是在数据库中,还是在文件系统上,或者直接放在内存中。这是一个重要的决定,会影响你的缓存的性能;有些缓存类型比其他类型快。

    缓存设置项位于配置文件的缓存配置中。

    在settings.py中增加:

    1. CACHES = {
    2. 'default': {
    3. 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
    4. 'TIMEOUT': 300, # 缓存超时时间,默认300,None表示永不过期,0表示立即过期
    5. 'OPTIONS': {
    6. 'MAX_ENTRIES': 300, # 最大缓存条数,默认300
    7. 'CULL_FREQUENCY': 3, # 当达到 MAX_ENTRIES 时,被删除的条目的比例。实际比例是 1 / CULL_FREQUENCY
    8. },
    9. 'KEY_PREFIX': '', # 缓存key的前缀(默认空
    10. 'VERSION': 1, # 缓存key的版本,默认1
    11. 'KEY_FUNCTION': hanshu_函数名, # 生成key的函数,默认函数会生成:【前缀:版本:key】
    12. }
    13. }

    上面是开发调试,即虚拟缓存的配置,其他的缓存,主要是BACKEND的不同:

    'django.core.cache.backends.db.DatabaseCache'
    'django.core.cache.backends.dummy.DummyCache'
    'django.core.cache.backends.filebased.FileBasedCache'
    'django.core.cache.backends.locmem.LocMemCache'
    'django.core.cache.backends.memcached.PyMemcacheCache'
    'django.core.cache.backends.memcached.PyLibMCCache'

    另外还有一个重要的配置项是LOCATION,指定缓存的位置。

    对于内存缓存,'django.core.cache.backends.locmem.LocMemCache',其LOCATION指定缓存的名字,相当于一个变量名,内存缓存就是内存中的一块区域,可以看成是一个字典,这里的LOCATION就是这个字典的名字,‘LOCATION’:‘unique-snowflake’,

    对于文件缓存,'django.core.cache.backends.filebased.FileBasedCache',其LOCATION指定缓存的文件夹位置,如'LOCATION': '/var/tmp/django_cache',

    对于数据库缓存,'django.core.cache.backends.db.DatabaseCache',其LOCATION指定缓存的数据库表名,如‘LOCATION’:‘my_cache_table’,需要执行创建表命令:python manage.py createcachetable

    对于Memcache——python-memcached,'django.core.cache.backends.memcached.PyMemcacheCache',其LOCATION指定另外一台机器:

    1)‘LOCATION’:‘127.0.0.1:11211’,  以IP和端口方式连接

    2)‘LOCATION’:‘unix:/tmp/memcached.sock’,以socket方式连接,一个文件,文件中写了连接信息,只能连本机。

    3)'LOCATION':['172.1.1.1:12211','172.1.1.2:12211',],一个列表指定多台机器,就是集群了,还可以列表中是元组项,指定权重:
    'LOCATION':[('172.1.1.1:12211',10),('172.1.1.2:12211',20),],

    对于'django.core.cache.backends.memcached.PyLibMCCache'同上面。

    应用:主要有全站使用、单独视图缓存、局部视图使用

    1、单独视图缓存

    首先配置settings,然后使用装饰器cache_page:

    1. # settings中的配置
    2. CACHES = {
    3. 'default': {
    4. 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
    5. 'LOCATION': os.path.join(BASE_DIR,'cache'),
    6. }
    7. }

    单独的视图函数使用装饰器来使用缓存:

    1. # 后台视图函数,引入装饰器,对单独函数使用缓存
    2. from django.views.decorators.cache import cache_page
    3. @cache_page(20) # 参数代表超时时间,单位是秒
    4. def cache(req):
    5. import time
    6. v = time.time()
    7. print(v)
    8. return HttpResponse(v)

    运行后,在文件夹中出现内容了:

     看运行结果:

     第一次请求时,视图函数运行打印了时间,后来的请求都没有运行,20秒后,缓存过期,函数又运行了,打印。

    2、局部缓存使用,(前端页面的部分缓存)

    使用在模板上,在模板中,先引入模板标签,即引入TemplateTag:{% load cache %}

    然后使用缓存:{% cache 10 缓存key %} 缓存内容 {% endcache %}

    视图函数:

    1. def part(req):
    2. import time
    3. v = time.time()
    4. print(v)
    5. return render(req,'part.html',{'v':v})

    前端模板:

    1. {% load cache %}
    2. html>
    3. <html lang="en">
    4. <head>
    5. <meta charset="UTF-8">
    6. <title>Titletitle>
    7. head>
    8. <body>
    9. <h1>{{ v }}h1>
    10. {% cache 20 key-11 %}
    11. <h3>{{ v }}h3>
    12. {% endcache %}
    13. body>
    14. html>

    这里会缓存

    的内容,在缓存中,其键的值会是“:1:key-11”。

    访问时:在缓存时间内,H1数据一直变化,H3是不变的,这个数据从缓存中来。

     后台的打印结果:

    每次请求都打印,即都执行了函数,说明函数没有缓存。 

    3、全站使用,(要使用中间件)

    一般使用两个中间件,一个放在中间件链的开始,一个放在最后,放在最后的中间件,执行process_request,放在第一个的中间件,执行process_response。

    这样放的理由:一个请求的到来,是需要经过所有process_request的,相当于过安检,安检过后,才能判断是否在缓存中,也就是在执行视图函数前判断缓存,如果不放在最后一个,有可能安检不通过也能获取数据了,这是放在最后中间件的原因,这个中间件是取缓存的功能,还要有一个中间件放在第一位置,主要执行数据的缓存功能,是执行process_response,这是因为对于返回的内容,其他中间件有可能会进行修改,如果不是第一个,就不是最后执行process_response的中间件,所缓存的内容可能不是最终的内容。(一定要与前面中间件的执行顺序相结合进行理解)。

    这两个中间件一个是'django.middleware.cache.UpdateCacheMiddleware'——更新缓存内容,实现内容的缓存和'django.middleware.cache.FetchFromCacheMiddleware'——从缓存中获取内容。

    配置如下:

    MIDDLEWARE = [
            'django.middleware.cache.UpdateCacheMiddleware',
            # 其他中间件。。。
            'django.middleware.cache.FetchFromCacheMiddleware',
    ]

    这样配置后,全站缓存就启用了。

    这时再访问前面的part页面时,H1和H3的内容都不变了,都进行了缓存。

     四、信号(Django预留的钩子)

    Django有一个“信号调度器(signal dispatcher)”,用来帮助解耦的应用获知框架内任何其他地方发生了操作。简单地说,信号允许某些 发送器 去通知一组 接收器 某些操作发生了。当许多代码段都可能对同一事件感兴趣时,信号特别有用。

    内置信号集 使用户代码能够获得 Django 自身某些操作的通知

    内置信号:

    Model signals
        pre_init                 # django的model执行其构造方法前,自动触发
        post_init               # django的model执行其构造方法后,自动触发
        pre_save             # django的model对象保存前,自动触发
        post_save            # django的model对象保存后,自动触发
        pre_delete            # django的model对象删除前,自动触发
        post_delete          # django的model对象删除后,自动触发
        m2m_changed     # django的model中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
        class_prepared      # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
    Management signals
        pre_migrate                 # 执行migrate命令前,自动触发
        post_migrate                # 执行migrate命令后,自动触发
    Request/response signals
        request_started             # 请求到来前,自动触发
        request_finished            # 请求结束后,自动触发
        got_request_exception       # 请求异常后,自动触发
    Test signals
        setting_changed             # 使用test测试修改配置文件时,自动触发
        template_rendered           # 使用test测试渲染模板时,自动触发
    Database Wrappers
        connection_created          # 创建数据库连接时,自动触发

    对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

    from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception

    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate

    from django.test.signals import setting_changed
    from django.test.signals import template_rendered

    from django.db.backends.signals import connection_created


    def callback(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)

    xxoo.connect(callback)
    # xxoo指上述导入的内容,即pre_init、post_init等,如pre_init.connect(callback)

    注册的时机,因为是要对所有的一类操作进行信号处理,所有要程序一运行就要注册上去。所以一般写在应用的__init__.py中。

    启动项目,会打印:

    xxoo_callback
    {'signal': , 'connection':

    测试model的信号pre_init和post_init:

    创建models类:

    1. from django.db import models
    2. # Create your models here.
    3. from django.db import models
    4. class User(models.Model):
    5. username = models.CharField(max_length=32)
    6. pwd = models.CharField(max_length=32)

    注册信号:

    1. from django.db.backends.signals import connection_created
    2. from django.core.signals import request_finished
    3. from django.core.signals import request_started
    4. from django.core.signals import got_request_exception
    5. from django.db.models.signals import class_prepared
    6. from django.db.models.signals import pre_init, post_init
    7. from django.db.models.signals import pre_save, post_save
    8. from django.db.models.signals import pre_delete, post_delete
    9. from django.db.models.signals import m2m_changed
    10. from django.db.models.signals import pre_migrate, post_migrate
    11. from django.test.signals import setting_changed
    12. from django.test.signals import template_rendered
    13. def callback(sender,**kwargs):
    14. print("xxoo_callback")
    15. print(sender,"-----",kwargs)
    16. def callback2(sender,**kwargs):
    17. print("xxoo_callback2")
    18. print(sender,"-----",kwargs)
    19. connection_created.connect(callback)
    20. pre_init.connect(callback)
    21. post_init.connect(callback2)

    视图函数:

    1. def signal(req):
    2. from midwares import models
    3. oo = models.User(username='root',pwd='123')
    4. return HttpResponse('ok')

    urls中增加 : path('signal/',views.signal),

    前端访问signal:打印结果

    xxoo_callback
    ----- {'signal': , 'args': (), 'kwargs': {'username': 'root', 'pwd': '123'}}
    xxoo_callback2
    ----- {'signal': , 'instance': }

    对于callback,是pre_init信息注册的,在实例化前执行,sender是,说明是User类触发的信号,参数中args是位置参数,这里没有传递位置参数,kwargs是我们创建User类对象时传递的参数,username=root,pwd=123,这些就可以在实例化前进行记录。

    对于callback2,是实例化后执行的,参数instance是实例化后的对象

    以上是Django定义的内置信号,下面我们自定义自己的信号:

    1)定义信号:
    import django.dispatch
    pizza_done = django.dispatch.Singnal(providing_args=["toppings","size"])

    1. def mysignal(req):
    2. from midwares import pizza_done # 从应用的__init__.py模块中引入,只需写应用的名,不必加__init__
    3. pizza_done.send(sender='调用者',toppings='123',size='456') # 自定义的信号,需要自己主动触发,触发就是调用send方法
    4. return HttpResponse('ok')

    2)注册信号:
    def callback(sender,**kwargs):
            print("callback")
            print(sender,kwargs)

    pizza_done.connect(callback)

    3)触发信号:
    from 路径 import pizza_done
    pizza_done.send(sender='seven',toppings=123,size=456)

    示例测试:

    在__init__.py中定义信号和注册信号:

    1. # 以下是定义信号
    2. import django.dispatch
    3. pizza_done = django.dispatch.Signal(providing_args=['toppings','size'])
    4. # 定义回调函数,注册信号
    5. def callback3(sender,**kwargs):
    6. print("自定义信号callback3")
    7. print(sender,kwargs)
    8. pizza_done.connect(callback3)

    触发信号:在视图函数中需要自己触发

    1. def mysignal(req):
    2. from midwares import pizza_done # 从应用的__init__.py模块中引入,只需写应用的名,不必加__init__
    3. pizza_done.send(sender='调用者',toppings='123',size='456') # 自定义的信号,需要自己主动触发,触发就是调用send方法
    4. return HttpResponse('ok')

    运行结果:

    自定义信号callback3
    调用者 {'signal': , 'toppings': '123', 'size': '456'}

    应用场景:预留插拔接口,如某操作后,需要发送提醒,一开始是短信,后来增加邮件,在增加微信、QQ等,这时使用信号,只要增加callback函数,注册信号就行。

    五、BootStrap,集成了css、js一个文件夹  ---   响应式+模板

    css:在前端网页中引入相应的css,在head中:

    响应式:

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Titletitle>
    6. <link rel="stylesheet" href="/static/bootstrap-5.1.3-dist/css/bootstrap.css">
    7. <style>
    8. .pg-header{
    9. height: 48px;
    10. background-color: black;
    11. }
    12. @media (max-width: 700px) {
    13. .extra{
    14. background-color: yellow;
    15. }
    16. }
    17. style>
    18. head>
    19. <body>
    20. <div class="pg-header extra">div>
    21. body>
    22. html>

     

     上面的页面,随着浏览器窗口宽度的变化,在700px以上,div的背景是黑色,缩小的700px以下时,背景变为黄色。这就是响应式。主要是使用@media,bootstrap中的container就是响应式容器

    bootstrap中提供了栅格的样式:col-sm-xx,col-md-xx

    js:需要先引入jQuery,然后引入bootstrap.js

  • 相关阅读:
    【C++11】shared_ptr智能指针使用详解
    01-Java的static关键字、单例、代码块、继承
    跨境电商一定要做跨境独立站的6个原因!一键对接电商API接口瞬间拥有全球各大平台几十亿商品
    CMake入门教程【核心篇】设置和使用缓存变量
    杨辉三角-
    限量,阿里百万级Redis小册开源,原理应用拓展一键完成
    DBeaver线下数据导入数据库表
    ruoyi-数据脱敏
    STM32f103入门(12)USART串口信息发送+接收
    vue通知(滚动)
  • 原文地址:https://blog.csdn.net/kaoa000/article/details/125777010