zoukankan      html  css  js  c++  java
  • Django缓存序列化信号

    缓存

    为什么要使用缓存?

    用户的每次请求如果都从数据库中获取数据模板渲染,将降低性能,增加服务器压力,而且客户端无法即时获得响应。如果将渲染后的结果放到缓存中,每次请求都会检查缓存中是否有对应的资源,如果有就会从缓存中获取数据。不过缓存都会有自己的生效时间,来保证数据的更新性。

      配置

        内存

    CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                }
            }
        }
    View Code

    可以在settings.py中单独填写CACHE_MIDDLEWARE_SECONDS = 数字, 来设置缓存超时时间,优先级高于CACHES中的TIMEOUT

      文件

    CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': 'D:cache',
                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                }
            }
        }
    View Code

      数据库

    CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table', # 数据库表
        }
        # 执行创建表命令 python manage.py createcachetable
    }
    View Code

    数据库是socket通信,其速度不如文件快,而且数据库所获得的数据需要进行渲染,而文件中是已经渲染过的字符串,因此速度要快于数据库

      Memcache缓存

    CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': '127.0.0.1:11211',
                'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                'OPTIONS':{
                    'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                    'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                }
            }
        }
    View Code

      应用

        全站应用

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

    全站缓存是在中间件中进行操作,请求进来时,通过FetchFromCacheMiddleware获取缓存资源,响应结果出去时,如果缓存中不存在请求起源,则通过django.middleware.cache.UpdateCacheMiddleware来将响应内容以字符串的形式缓存下来。

    全站缓存适用于实时性要求不高的网站,比如个人博客

        单独试图

    方式一:

    方式一:
            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)),
            ]
    View Code

    方式二:在路由中进行配置

    from django.views.decorators.cache import cache_page
    
    urlpatterns = [
        url(r'^test.html/$', cache_page(5)(views.test)),
        # 将cache_page(5) 加到视图前面
    ]
    View Code

        

        局部模板

     a. 引入TemplateTag
    
            {% load cache %}
    
        b. 使用缓存
    
            {% cache 5000 缓存key %}
                缓存内容
            {% endcache %}
    
    
    示例:
    #HTML:
    {% load cache %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
            {% cache 5 'asda' %}
                <h1>{{ date }}</h1>
            {% endcache %}
    
    </body>
    </html>
    
    #View:
    def index(request):
        date = time.time()
        return render(request,"index.html",{"date":date})
    View Code

    信号

      内置信号

    from django.db.models.signals import pre_save
    Model signals
    		pre_init                    # django的modal执行其构造方法前,自动触发
    		post_init                   # django的modal执行其构造方法后,自动触发
    		pre_save                    # django的modal对象保存前,自动触发
    		post_save                   # django的modal对象保存后,自动触发
    		pre_delete                  # django的modal对象删除前,自动触发
    		post_delete                 # django的modal对象删除后,自动触发
    		m2m_changed                 # django的modal中使用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          # 创建数据库连接时,自动触发
    

      示例

    项目目录下的同名目录下的__init__.py中写入,因为这个文件在项目运行时会自动运行
    
    from django.db.models.signals import pre_save
    
    def callback1(sender,**kwargs):
    
        print("callback1",sender,kwargs)
    
    pre_save.connect(callback1)
    
    View:
    def users(request):
        user_obj=models.UserInfo(name='xiaobai',pwd='123',ut_id=1)
        user_obj.save()
        return HttpResponse("OK")
    
    打印结果:
    callback1 <class 'app01.models.UserInfo'> {'signal': <django.db.models.signals.ModelSignal object at 0x0000029CCE6828D0>, 'instance': <UserInfo: UserInfo object>, 'raw': False, 'using': 'default', 'update_fields': None}
    View Code

      自定义信号

    新建模块命名为mysignal,写入:
    import django.dispatch
    pizza_done=django.dispatch.Signal(providing_args=["toppings","size"])
    
    def callback(sender,**kwargs):
        print("xiaobai_callback",sender,kwargs)
    
    pizza_done.connect(callback)
    
    View:
    
    def users(request):
        user_obj=models.UserInfo(name='xiaobai2',pwd='123',ut_id=1)
        user_obj.save()
        from mysignal import pizza_done
        pizza_done.send(sender='xiaobai',toppings=request,size=666)
        return HttpResponse("OK")
    
    打印结果:
    xiaobai_callback xiaobai {'signal': <django.dispatch.dispatcher.Signal object at 0x000001F9F094B860>, 'toppings': <WSGIRequest: GET '/users.html'>, 'size': 666}

    性能相关

    示例:
       models:
    class UserInfo(models.Model):
        name=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        ut=models.ForeignKey(to='UserType')
    
    class UserType(models.Model):
        name=models.CharField(max_length=32)
    
    View:
        user_list=models.UserInfo.objects.all()
        for user in user_list:
               #取本表数据,涉及多表时性能会变差
        select_related 主动连表查询(foreign_key),可以填入多个字段,select_related 只能进行OneToOne和ForeignKey查询,不能进行ManyToMany查询
        user_list=models.UserInfo.objects.all().select_related(foreign_key字段)
        for user in user_list:
            #取当前表数据和FK关联字段数据
        user_list=models.UserInfo.objects.values(...)
        for user in user_list:
            #取当前表数据和关联字段数据
        prefetch_related 可以填入多个字段
        user_list=models.UserInfo.objects.all().prefetch_related(foreign_key字段)
        [obj,obj,obj,...]
        查询用户表user_list
        把用户表中所有的ut_id拿到,用户类型ID[1,2,3,..],不大于UserType表总数
        select * from UserType where id in [1,2,3,...]
        补充:
            user_list=models.UserInfo.objects.all().only("name") 只取某个字段
            user_list=models.UserInfo.objects.all().defer("name")排除当前字段
            取符合填入字段的数据性能较好

    分页

    在项目目录下创建utils目录,新建page.py,写入:
    """
    使用方法:
    
    from utils.page import Pagination
    def users(request):
        current_page = int(request.GET.get('page',1))
    
        total_item_count = models.UserInfo.objects.all().count()
        # page_obj = Pagination(current_page,total_item_count,request.path_info)
        page_obj = Pagination(current_page,total_item_count,'/users.html')
    
        user_list = models.UserInfo.objects.all()[page_obj.start:page_obj.end]
    
        return render(request,'users.html',{'user_list':user_list,'page_html':page_obj.page_html()})
    
    
    """
    
    
    from django.utils.safestring import mark_safe
    class Pagination(object):
    
        def __init__(self,current_page,total_item_count,base_url,per_page_count=10,show_pager_count=11):
            """
            :param current_page:  当前页
            :param total_item_count: 数据库数据总条数
            :param base_url: 分页前缀URL
            :param per_page_count:   每页显示数据条数
            :param show_pager_count: 对多显示的页码
            """
            self.current_page = current_page
            self.total_item_count = total_item_count
            self.base_url = base_url
            self.per_page_count = per_page_count
            self.show_pager_count = show_pager_count
    
            max_pager_num, b = divmod(total_item_count, per_page_count)
            if b:
                max_pager_num += 1
            self.max_pager_num = max_pager_num
    
    
        @property
        def start(self):
            """
    
            :return:
            """
            return (self.current_page-1)* self.per_page_count
    
        @property
        def end(self):
            """
    
            :return:
            """
            return self.current_page * self.per_page_count
    
        def page_html(self):
            """
    
            :return:
            """
            page_list = []
    
            if self.current_page == 1:
                prev = ' <li><a href="#">上一页</a></li>'
            else:
                prev = ' <li><a href="%s?page=%s">上一页</a></li>' % (self.base_url,self.current_page - 1,)
            page_list.append(prev)
    
            half_show_pager_count = int(self.show_pager_count / 2)
    
            # 数据特别少,15条数据=2页
            if self.max_pager_num < self.show_pager_count:
                # 页码小于11
                pager_start = 1
                pager_end = self.max_pager_num + 1
            else:
                if self.current_page <= half_show_pager_count:
                    pager_start = 1
                    pager_end = self.show_pager_count + 1
                else:
                    if self.current_page + half_show_pager_count > self.max_pager_num:
                        pager_start = self.max_pager_num - self.show_pager_count + 1
                        pager_end = self.max_pager_num + 1
                    else:
                        pager_start = self.current_page - half_show_pager_count
                        pager_end = self.current_page + half_show_pager_count + 1
    
            for i in range(pager_start, pager_end):
                if i == self.current_page:
                    tpl = ' <li class="active"><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
                else:
                    tpl = ' <li><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
                page_list.append(tpl)
    
            if self.current_page == self.max_pager_num:
                nex = ' <li><a href="#">下一页</a></li>'
            else:
                nex = ' <li><a href="%s?page=%s">下一页</a></li>' % (self.base_url,self.current_page + 1,)
            page_list.append(nex)
    
            return mark_safe(''.join(page_list))

    自定义序列化

    from datetime import datetime
    from datetime import date
    import json
    
    
    class JsonCustomEncoder(json.JSONEncoder):
        def default(self, field):
            if isinstance(field, datetime):
                return field.strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(field, date):
                return field.strftime('%Y-%m-%d')
            else:
                return json.JSONEncoder.default(self, field)
    
    data_list = [
        {'name':'alex','age':19, 'ctime': datetime.now()},
        {'name':'egon','age':19, 'ctime': datetime.now()},
        {'name':'eric','age':19, 'ctime': datetime.now()},
        {'name':'rain','age':19, 'ctime': datetime.now()}
    ]
    
    val = json.dumps(data_list,cls=JsonCustomEncoder)
    print(val)
  • 相关阅读:
    怎样创建动态扩容数组?
    怎样终止一个线程?
    模式识别
    基于Linux根据僵尸网络病毒平台《比尔盖茨》
    web.xml在&lt;init-param&gt;一个错误
    DTD学习笔记
    Java排序算法(四):Shell排序
    VC6迁移到VS2008几个问题——良好的代码,从我做起,从现在开始。
    Maven 建 Struts2 基本实现 CURD Controller
    Andy&#39;s First Dictionary
  • 原文地址:https://www.cnblogs.com/c491873412/p/7563261.html
Copyright © 2011-2022 走看看