zoukankan      html  css  js  c++  java
  • Django 补充models操作,中间件, 缓存,信号,分页

    1、Model 一对多 补充

    models如下:

    class UserType(models.Model):
        caption = models.CharField(max_length=16)
    
    class UserInfo(models.Model):
        username = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        user_type = models.ForeignKey('UserType')

    通过queryset查询用户为CEO的用户

    >>> from app01.models import UserInfo,UserType
    >>> q = UserInfo.objects.filter(user_type__caption='CEO')
    >>> print(q)
    <QuerySet [<UserInfo: UserInfo object>]>
    >>> print(q[0])
    UserInfo object
    >>> print(q[0].username)
    james
    >>> print(q[0].pwd)
    45569
    >>> print(q[0].user_type.caption)
    CEO
    

     用values,value_list查询

    >>> q = UserInfo.objects.filter(user_type__caption='CEO').values('username','pwd','user_type__caption')
    >>> q
    <QuerySet [{'pwd': '45569', 'username': 'james', 'user_type__caption': 'CEO'}]>
    >>> q[0]
    {'pwd': '45569', 'username': 'james', 'user_type__caption': 'CEO'}
    

     value_list 返回元组可以应用到from的select标签

    >>> q = UserInfo.objects.filter(user_type__caption='CEO').values_list('username','pwd','user_type__caption')
    >>> q
    <QuerySet [('james', '45569', 'CEO')]>
    >>> q[0]
    ('james', '45569', 'CEO')
    

    2、model操作 F/Q

    F:使用查询条件的值


    temp = salary+500
    models.UserInfo.objects.filter().update(salary=temp)
    update userinfo set salary=salary+500

    >>> from django.db.models import F
    >>> print(models.UserInfo.objects.values('salary'))
    <QuerySet [{'salary': '6500'}, {'salary': '6500'}, {'salary': '6500'}]>
    >>> print(models.UserInfo.objects.filter().update(salary=F('salary')+500))
    3
    >>> print(models.UserInfo.objects.values('salary'))
    <QuerySet [{'salary': '7000'}, {'salary': '7000'}, {'salary': '7000'}]>



    Q:构造搜索条件
    1、传参

    >>> models.UserInfo.objects.filter(id=3,user='jasonwang')
    <QuerySet [<UserInfo: jasonwang>]>
    >>> print(models.UserInfo.objects.filter(id=3,user='jasonwang').query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE ("app01_userinfo"."id" = 3 AND "app01_userinfo"."user" = jasonwang)



    2、传字典

    >>> d = {'id':3,'user':'jasonwang'}
    >>> models.UserInfo.objects.filter(**d)
    <QuerySet [<UserInfo: jasonwang>]>

    <input name='id' />
    <input name='name' />
    获取用户输入,并构造成字典:
    models.UserInfo.objects.filter(**d)
    3、传Q对象
    models.UserInfo.objects.filter(Q对象)

    from django.db.models import Q

    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 2))
    # q1.children.append(('id', 3))

    # models.Tb1.objects.filter(q1)

    >>> q1.connector = 'OR'
    >>> q1.children.append(('id',1))
    >>> q1.children.append(('id',2))
    >>> q1.children.append(('id',3))
    >>> qq = models.UserInfo.objects.filter(q1)
    >>> print(qq.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE ("app01_userinfo"."id" = 1 OR "app01_userinfo"."id" = 2 OR "app01_userinfo"."id" = 3)

    # con = Q()
    #
    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 2))
    # q1.children.append(('id', 3))
    #
    # q2 = Q()
    # q2.connector = 'OR'
    # q2.children.append(('status', '在线'))
    #
    # con.add(q1, 'AND')
    # con.add(q2, 'AND')
    #
    # models.Tb1.objects.filter(con)

    >>> q1.connector = 'OR'
    >>> q1.children.append(('id',1))
    >>> q1.children.append(('id',2))
    >>> q1.children.append(('id',3))
    >>> qq = models.UserInfo.objects.filter(q1)
    >>> print(qq.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE ("app01_userinfo"."id" = 1 OR "app01_userinfo"."id" = 2 OR "app01_userinfo"."id" = 3)
    >>> q2 = Q()
    >>> q2.connector = 'OR'
    >>> q2.children.append(('address','haidian'))
    >>> con = Q()
    >>> con.add(q1,'AND')
    <Q: (OR: ('id', 1), ('id', 2), ('id', 3))>
    >>> con.add(q2,'AND')
    <Q: (AND: (OR: ('id', 1), ('id', 2), ('id', 3)), ('address', 'haidian'))>
    >>> qq = models.UserInfo.objects.filter(con)
    >>> print(qq.query)
    SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE (("app01_userinfo"."id" = 1 OR "app01_userinfo"."id" = 2 OR "app01_userinfo"."id" = 3) AND "app01_userinfo"."address" = haidian)
    >>> print(qq)
    <QuerySet [<UserInfo: jason>]>
    >>> print(qq[0])
    jason
    >>> 

    3、model多对多操作

    - 创建

    a. 方式一:
    class B2G(models.Model):
    b_id = models.ForeignKey('Boy')
    g_id = models.ForeignKey('Girl')

    class Boy(models.Model):

    username = models.CharField(max_length=16)

    class Girl(models.Model):

    name = models.CharField(max_length=16)

    b. 方式二:
    class Boy(models.Model):

    username = models.CharField(max_length=16)
    # girl_set
    class Girl(models.Model):

    name = models.CharField(max_length=16)

    b = models.ManyToManyField('Boy')


    - 操作:
    添加:
    正向

    g1 = models.Girl.objects.get(id=1)
    
    g1.b.add(models.Boy.objects.get(id=1))
    g1.b.add(1)
    
    bs = models.Boy.objects.all()
    g1.b.add(*bs)
    g1.b.add(*[1,2,3])

    反向

    b1 = models.Boy.objects.get(id=1)
    b1.girl_set.add(1)
    b1.girl_set.add(models.Girl.objects.all())
    
    b1.girl_set.add(*[1,2,3,4])


    ...
    删除:

    g1 = models.Girl.objects.get(id=1)
    g1.b.clear() # 清空和girl ID=1所关联的所有数据
    
    g1.b.remove(2) 
    g1.b.remove(*[1,2])


    查询:

    g1 = models.Girl.objects.get(id=1) # SQL
    g1.b.all()    # SQL
    g1.b.filter().count()
    
    b1 = models.Boy.objects.get(id=1)
    b1.girl_set.all()
    
    models.Girl.objects.all().values('id','name', 'b__username')
    models.Boy.objects.all().values('id','username', 'girl__name')

    更新:


    ORM:
    python操作数据库模块:
    MySQLdb
    pymysql

    原生SQL
    # from django.db import connection
    # cursor = connection.cursor()
    # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
    # row = cursor.fetchone()

    4、中间件

    中间件介绍:

    中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。 
    每个中间件都会负责一个功能,例如,AuthenticationMiddleware,与sessions处理相关。

    激活中间件:

     

    需要在settings.py配置文件中,配置MIDDLEWARE_CLASSES:

    MIDDLEWARE_CLASSES = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        # 'django.middleware.cache.FetchFromCacheMiddleware',
    ]

    当然你也可以不试用任何的中间件,这个可以设置为空。

    中间件顺序

    一般我们我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下,process request 和 process response的执行顺序正好相反,当有请求过来的时候,默认从上倒下执行!然后在返回的时候从下面在返回回去,如下图所示。

    也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。 
    中间件不用继承自任何类(可以继承 object ),

    自定义一个中间件:

    中间件中可以定义四个方法,分别是:

    • process_request(self,request)
    • process_view(self, request, callback, callback_args, callback_kwargs)
    • process_exception(self, request, exception)
    • process_response(self, request, response)

    process_exception 这个方法只有在出现错误的时候才会触发

    先写一个自定义中间件,然后在看他的原理和源码,首先把自定义的中间件加到settings文件中:

    写类:
    process_request
    process_view
    process_exception
    process_response

    from django.shortcuts import HttpResponse
    from django.utils import deprecation
    class M1(deprecation.MiddlewareMixin):
    def process_request(self, request):
    print('M1.process_request')
    # return HttpResponse('滚')

    def process_view(self, request, callback, callback_args, callback_kwargs):
    print('m1.process_view')

    def process_exception(self, request, exception):
    print('m1.process_exception')

    def process_response(self, request, response):
    print('M1.process_response')
    return response

    def process_template_response(self,request,response):
    print('template')


    class M2(deprecation.MiddlewareMixin):
    def process_request(self, request):
    print('M2.process_request')
    def process_view(self, request, callback, callback_args, callback_kwargs):
    print('m2.process_view')
    def process_exception(self, request, exception):
    print('m2.process_exception')

    def process_response(self, request, response):
    print('M2.process_response')
    return response

    django 1.10中自定义中间建需要制定继承的deprecation.MiddlewareMixin类,否则会出现如下报错

    mw_instance = middleware(handler)
    TypeError: object() takes no parameters


    1.10配置文件:
    MIDDLEWARE =

    MIDDLEWARE = [
        'md.mymiddle.M1',
        'md.mymiddle.M2',
        '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',
    ]

    测试使用url和views

     url(r'^md/',views.md),
    def md(request):
        return HttpResponse('ok')

    查看输出结果:

    M1.process_request
    M2.process_request
    m1.process_view
    m2.process_view
    M2.process_response
    M1.process_response

    5 Django的Request/Response处理流程的分析

    一、 处理过程的核心概念

    如下图所示django的总览图,整体上把握以下django的组成

    核心在于中间件middleware,django所有的请求、返回都由中间件来完成。

    中间件,就是处理HTTP的request和response的,类似插件,比如有Request中间件、view中间件、response中间件、exception中间件等,Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义。大致的程序流程图如下所示:


    首先,Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义, 一个HTTP请求,将被这里指定的中间件从头到尾处理一遍,暂且称这些需要挨个处理的中间件为处理链,如果链中某个处理器处理后没有返回response,就把请求传递给下一个处理器;如果链中某个处理器返回了response,直接跳出处理链由response中间件处理后返回给客户端,可以称之为短路处理。

    上面的两张流程图可以大致描述Django处理request的流程,按照流程图2的标注,可以分为以下几个步骤:

    1. 用户通过浏览器请求一个页面

    2. 请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求

    3. URLConf通过urls.py文件和请求的URL找到相应的View

    4. View Middlewares被访问,它同样可以对request做一些处理或者直接返回response

    5. 调用View中的函数

    6. View中的方法可以选择性的通过Models访问底层的数据

    7. 所有的Model-to-DB的交互都是通过manager完成的

    8. 如果需要,Views可以使用一个特殊的Context

    9. Context被传给Template用来生成页面

    a. Template使用Filters和Tags去渲染输出

    b. 输出被返回到View

    c. HTTPResponse被发送到Response Middlewares

    d. 任何Response Middlewares都可以丰富response或者返回一个完全不同的response

    e. Response返回到浏览器,呈现给用户

    上述流程中最主要的几个部分分别是:Middleware(中间件,包括request, view, exception, response),URLConf(url映射关系),Template(模板系统),下面一一介绍一下。

    1、Middleware(中间件)

    Middleware并不是Django所独有的东西,在其他的Web框架中也有这种概念。在Django中,Middleware可以渗入处理流程的四个阶段:request,view,response和exception,相应的,在每个Middleware类中都有rocess_request,process_view, process_response 和 process_exception这四个方法。你可以定义其中任意一个活多个方法,这取决于你希望该Middleware作用于哪个处理阶段。每个方法都可以直接返回response对象。

    Middleware是在Django BaseHandler的load_middleware方法执行时加载的,加载之后会建立四个列表作为处理器的实例变量:

    _request_middleware:process_request方法的列表

    _view_middleware:process_view方法的列表

    _response_middleware:process_response方法的列表

    _exception_middleware:process_exception方法的列表

     Django的中间件是在其配置文件(settings.py)的MIDDLEWARE_CLASSES元组中定义的。在MIDDLEWARE_CLASSES中,中间件组件用字符串表示:指向中间件类名的完整Python路径。

    Django项目的安装并不强制要求任何中间件,如果你愿意,MIDDLEWARE_CLASSES可以为空。中间件出现的顺序非常重要:在request和view的处理阶段,Django按照MIDDLEWARE_CLASSES中出现的顺序来应用中间件,而在response和exception异常处理阶段,Django则按逆序来调用它们。也就是说,Django将MIDDLEWARE_CLASSES视为view函数外层的顺序包装子:在request阶段按顺序从上到下穿过,而在response则反过来。以下两张图可以更好地帮助你理解:

    2、URLConf(URL映射)

    如果处理request的中间件都没有直接返回response,那么Django会去解析用户请求的URL。URLconf就是Django所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。通过这种方式可以告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。具体的,在Django项目的配置文件中有ROOT_URLCONF常量,这个常量加上根目录”/”,作为参数来创建django.core.urlresolvers.RegexURLResolver的实例,然后通过它的resolve方法解析用户请求的URL,找到第一个匹配的view。

    原版本: 如果process_request中有return, 则所有的process_response执行一遍

    6、缓存

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

    举个例子来说:如果访问量比较大的时候,有很多相同的操作比如:有时候请求的数据比如访问同一条数据,或者同一个页面的时候,其实是没必要的。

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

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

    1、配置

    a、开发调试

    # 此为开始调试用,实际内部不做任何操作
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     # 引擎
                    'TIMEOUT': 300,                                               # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                    'OPTIONS':{
                        'MAX_ENTRIES': 300,                                       # 最大缓存个数(默认300)
                        'CULL_FREQUENCY': 3,                                      # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                    },
                    'KEY_PREFIX': '',                                             # 缓存key的前缀(默认空)
                    'VERSION': 1,                                                 # 缓存key的版本(默认1)
                    'KEY_FUNCTION' 函数名                                          # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
                }
            }
    
    
        # 自定义key
        def default_key_func(key, key_prefix, version):
            """
            Default function to generate keys.
    
            Constructs the key used by all other methods. By default it prepends
            the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
            function with custom key making behavior.
            """
            return '%s:%s:%s' % (key_prefix, version, key)
    
        def get_key_func(key_func):
            """
            Function to decide which key function to use.
    
            Defaults to ``default_key_func``.
            """
            if key_func is not None:
                if callable(key_func):
                    return key_func
                else:
                    return import_string(key_func)
            return default_key_func
    View Code

    b、内存

       # 此缓存将内容保存至内存的变量中
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                    'LOCATION': 'unique-snowflake',
                }
            }
    
        # 注:其他配置同开发调试版本
    View Code

    c、文件

    # 此缓存将内容保存至文件
        # 配置:
    
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                    'LOCATION': '/var/tmp/django_cache',
                }
            }
        # 注:其他配置同开发调试版本
    View Code

    d、数据库

      # 此缓存将内容保存至数据库
    
        # 配置:
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                    'LOCATION': 'my_cache_table', # 数据库表
                }
            }
    
        # 注:执行创建表命令 python manage.py createcachetable
    View Code

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

    # 此缓存使用python-memcached模块连接memcache
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': '127.0.0.1:11211',
            }
        }
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': 'unix:/tmp/memcached.sock',
            }
        }   
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                'LOCATION': [
                    '172.19.26.240:11211',
                    '172.19.26.242:11211',
                ]
            }
        }
    View Code

    f、Memcache缓存(pylibmc模块)

        # 此缓存使用pylibmc模块连接memcache
        
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                'LOCATION': '127.0.0.1:11211',
            }
        }
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                'LOCATION': '/tmp/memcached.sock',
            }
        }   
    
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                'LOCATION': [
                    '172.19.26.240:11211',
                    '172.19.26.242:11211',
                ]
            }
        }
    View Code

    2、应用

    a. 全站使用

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

    b. 单独视图缓存

        方式一:
            from django.views.decorators.cache import cache_page
    
            @cache_page(60 * 15)
            def my_view(request):
                ...
    
        方式二:
            from django.views.decorators.cache import cache_page
    
            urlpatterns = [
                url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
            ]
    View Code

    c、局部视图使用

      a. 引入TemplateTag
    
            {% load cache %}
    
        b. 使用缓存
    
            {% cache 5000 缓存key %}
                缓存内容
            {% endcache %}
    View Code

    更多:猛击这里

    7.序列化

    关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

    1、serializers

    from django.core import serializers
     
    ret = models.BookType.objects.all()
     
    data = serializers.serialize("json", ret)
    

     2、json.dumps

    import json
     
    #ret = models.BookType.objects.all().values('caption')
    ret = models.BookType.objects.all().values_list('caption')
     
    ret=list(ret)
     
    result = json.dumps(ret)
    

     由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

    import json 
    from datetime import date 
    from datetime import datetime 
       
    class JsonCustomEncoder(json.JSONEncoder): 
        
        def default(self, field): 
         
            if isinstance(field, datetime): 
                return o.strftime('%Y-%m-%d %H:%M:%S') 
            elif isinstance(field, date): 
                return o.strftime('%Y-%m-%d') 
            else: 
                return json.JSONEncoder.default(self, field) 
       
       
    # ds = json.dumps(d, cls=JsonCustomEncoder) 

    8、信号

    Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者.

    1、Django内置信号

    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          # 创建数据库连接时,自动触发
    

     对于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指上述导入的内容
    View Code
    from django.core.signals import request_finished
    from django.dispatch import receiver
    
    @receiver(request_finished)
    def my_callback(sender, **kwargs):
        print("Request finished!")
    View Code

    2、自定义信号

    a. 定义信号

    import django.dispatch
    pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

    b. 注册信号

    def callback(sender, **kwargs):
        print("callback")
        print(sender,kwargs)
     
    pizza_done.connect(callback)

    c. 触发信号

    from 路径 import pizza_done
     
    pizza_done.send(sender='seven',toppings=123, size=456)

    由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

    更多:猛击这里

    8、分页(公共插件) 

    一、Django内置分页

    Paginator
    

     二、自定义分页

    分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

    1、设定每页显示数据条数

    2、用户输入页码(第一页、第二页...)

    3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    4、在数据表中根据起始位置取值,页面上输出数据


    需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

    1、设定每页显示数据条数

    2、用户输入页码(第一页、第二页...)

    3、设定显示多少页号

    4、获取当前数据总条数

    5、根据设定显示多少页号和数据总条数计算出,总页数

    6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    7、在数据表中根据起始位置取值,页面上输出数据

    8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

    #!/usr/bin/env python
    # _*_coding:utf-8_*_
    from django.utils.safestring import mark_safe
     
    class PageInfo(object):
        def __init__(self,current,totalItem,peritems=5):
            self.__current=current
            self.__peritems=peritems
            self.__totalItem=totalItem
        def From(self):
            return (self.__current-1)*self.__peritems
        def To(self):
            return self.__current*self.__peritems
        def TotalPage(self):  #总页数
            result=divmod(self.__totalItem,self.__peritems)
            if result[1]==0:
                return result[0]
            else:
                return result[0]+1
     
    def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数
        perPager=11
        #总页数<11
        #0 -- totalpage
        #总页数>11
            #当前页大于5 currentPage-5 -- currentPage+5
                #currentPage+5是否超过总页数,超过总页数,end就是总页数
            #当前页小于5 0 -- 11
        begin=0
        end=0
        if totalpage <= 11:
            begin=0
            end=totalpage
        else:
            if currentPage>5:
                begin=currentPage-5
                end=currentPage+5
                if end > totalpage:
                    end=totalpage
            else:
                begin=0
                end=11
        pager_list=[]
        if currentPage<=1:
            first="<a href=''>首页</a>"
        else:
            first="<a href='%s%d'>首页</a>" % (baseurl,1)
        pager_list.append(first)
     
        if currentPage<=1:
            prev="<a href=''>上一页</a>"
        else:
            prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
        pager_list.append(prev)
     
        for i in range(begin+1,end+1):
            if i == currentPage:
                temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
            else:
                temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
            pager_list.append(temp)
        if currentPage>=totalpage:
            next="<a href='#'>下一页</a>"
        else:
            next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
        pager_list.append(next)
        if currentPage>=totalpage:
            last="<a href=''>末页</a>"
        else:
            last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
        pager_list.append(last)
        result=''.join(pager_list)
        return mark_safe(result)   #把字符串转成html语言
    分页实例

    总结,分页时需要做三件事:

    • 创建处理分页数据的类
    • 根据分页数据获取数据
    • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
  • 相关阅读:
    [更新] Jetbrains IntelliJ IDEA 2019 的许可证密钥
    GoldenDict(for Linux)配置无道词典
    MATLAB datenum日期转换为Python日期
    【科研】之科研镜像
    ubuntu开机自动挂载硬盘
    Python列表(list)所有元素的同一操作
    yum运行报错:File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: ^SyntaxError: invalid syntax
    Glibc编译报错:*** These critical programs are missing or too old: as ld gcc
    Glibc编译报错:*** LD_LIBRARY_PATH shouldn't contain the current directory when*** building glibc. Please change the environment variable
    Python编译升级
  • 原文地址:https://www.cnblogs.com/jasonwang-2016/p/5910479.html
Copyright © 2011-2022 走看看