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
b、内存
# 此缓存将内容保存至内存的变量中
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}
# 注:其他配置同开发调试版本
c、文件
# 此缓存将内容保存至文件
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同开发调试版本
d、数据库
# 此缓存将内容保存至数据库
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
}
}
# 注:执行创建表命令 python manage.py createcachetable
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',
]
}
}
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',
]
}
}
2、应用
a. 全站使用
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware',
]
CACHE_MIDDLEWARE_ALIAS = ""
CACHE_MIDDLEWARE_SECONDS = ""
CACHE_MIDDLEWARE_KEY_PREFIX = ""
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)),
]
c、局部视图使用
a. 引入TemplateTag
{% load cache %}
b. 使用缓存
{% cache 5000 缓存key %}
缓存内容
{% endcache %}
更多:猛击这里
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指上述导入的内容
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")
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][下一页]