Django 补充models操作,中间件, 缓存,信号,分页

时间:2021-03-01 19:19:22

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的执行顺序正好相反,当有请求过来的时候,默认从上倒下执行!然后在返回的时候从下面在返回回去,如下图所示。

Django 补充models操作,中间件, 缓存,信号,分页

也就是说,每一个请求都是先通过中间件中的 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文件中:

Django 补充models操作,中间件, 缓存,信号,分页

 

写类:
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的组成

Django 补充models操作,中间件, 缓存,信号,分页

 

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

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

Django 补充models操作,中间件, 缓存,信号,分页

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页


首先,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则反过来。以下两张图可以更好地帮助你理解:

Django 补充models操作,中间件, 缓存,信号,分页

Django 补充models操作,中间件, 缓存,信号,分页

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、开发调试

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
# 此为开始调试用,实际内部不做任何操作
# 配置:
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、内存

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
   # 此缓存将内容保存至内存的变量中
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}

# 注:其他配置同开发调试版本
View Code

c、文件

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
# 此缓存将内容保存至文件
# 配置:

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同开发调试版本
View Code

d、数据库

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
  # 此缓存将内容保存至数据库

# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
}
}

# 注:执行创建表命令 python manage.py createcachetable
View Code

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

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
# 此缓存使用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模块)

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
    # 此缓存使用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. 全站使用

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
  使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

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

CACHE_MIDDLEWARE_ALIAS = ""
CACHE_MIDDLEWARE_SECONDS = ""
CACHE_MIDDLEWARE_KEY_PREFIX = ""
View Code

b. 单独视图缓存

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
    方式一:
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、局部视图使用

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
  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内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
 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

 

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
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][下一页]

Django 补充models操作,中间件, 缓存,信号,分页Django 补充models操作,中间件, 缓存,信号,分页
#!/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][下一页]