一、自定义分页(优势在于能够保存搜索条件)

"""
分页组件使用示例:
1) 先取出所有数据USER_LIST
2) 实例化:
obj = Pagination(request.GET.get('page',1), len(USER_LIST), request)
3) 对所有数据列表切片(即切出一页数据):
page_user_list = USER_LIST[obj.start:obj.end]
4) 返回给页面:
return render(request,'index.html',{'users': page_user_list, 'obj': obj})
5) 模板页面通过 {{ obj.page_html|safe }} 渲染页码
""" class Pagination(object): def __init__(self, current_page_num, all_count, request, per_page_num=2, pager_count=11):
"""
封装分页相关数据
:param current_page_num: 当前访问页的数字
:param all_count: 分页数据中的数据总条数
:param request: 请求对象
:param per_page_num: 每页显示的数据条数
:param pager_count: 最多显示的页码个数
"""
try:
current_page_num = int(current_page_num)
except Exception as e:
current_page_num = 1 if current_page_num < 1:
current_page_num = 1 self.current_page_num = current_page_num
self.all_count = all_count
self.per_page_num = per_page_num # 实际总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager
self.pager_count = pager_count # 显示的页码数
self.pager_count_half = int((pager_count - 1) / 2) # 显示的页码数减1的一半 # 保存搜索条件
import copy
self.params=copy.deepcopy(request.GET) # {"a":"1","b":"2"} @property
def start(self):
return (self.current_page_num - 1) * self.per_page_num @property
def end(self):
return self.current_page_num * self.per_page_num def page_html(self):
# 如果总页码 <= 11:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 如果当前页<=5
if self.current_page_num <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1
# 当前页大于5
else:
# 页码翻到最后
if (self.current_page_num + self.pager_count_half) > self.all_pager:
pager_start = self.all_pager - self.pager_count + 1
pager_end = self.all_pager + 1
else: # 正常取前五页后五页
pager_start = self.current_page_num - self.pager_count_half
pager_end = self.current_page_num + self.pager_count_half+1 page_html_list = []
self.params["page"] = 1
first_page = '<li><a href="?%s">首页</a></li>' % (self.params.urlencode())
page_html_list.append(first_page) if self.current_page_num <= 1:
prev_page = '<li class="disabled"><a href="javascript:void(0);">上一页</a></li>' # 第一页的上一页禁用
else:
self.params["page"] = self.current_page_num - 1
prev_page = '<li><a href="?%s">上一页</a></li>' % (self.params.urlencode())
page_html_list.append(prev_page) for i in range(pager_start, pager_end):
self.params["page"] = i # 原搜索条件中加上页码
if i == self.current_page_num:
temp = '<li class="active"><a href="?%s">%s</a></li>' %(self.params.urlencode(), i)
else:
temp = '<li><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,)
page_html_list.append(temp) if self.current_page_num >= self.all_pager:
next_page = '<li class="disabled"><a href="javascript:void(0);">下一页</a></li>' # 最后一页的下一页禁用
else:
self.params["page"] = self.current_page_num + 1
next_page = '<li><a href="?%s">下一页</a></li>' % (self.params.urlencode())
page_html_list.append(next_page) self.params["page"] = self.all_pager
last_page = '<li><a href="?%s">尾页</a></li>' % (self.params.urlencode())
page_html_list.append(last_page) return ''.join(page_html_list)

  分页中关于保存搜索条件关键点总结:

  我们知道,request.GET和request.POST是QueryDict类型,而且是不可更改的,因为这是用户提交过来的原生数据,Django处于安全考虑,在源码中通过对request.GET和request.POST提交过来的QueryDict设置_mutable = True,即不可更改,我们在开发中如果想要修改的话,可以通过拷贝一份得到其副本(params=copy.deepcopy(request.GET) ),而副本是可以修改的(源码中将拷贝的副本的_mutable 设为了False,所以可以修改),根据需求改完副本后可以通过urlencode()方法将副本的QueryDict数据按照urlencoded格式(键值对以&连接,即a=1&b=2)拼接成字符串。

二、FBV和CBV

1、FBV

  FBV(function base views),就是在视图里使用函数处理请求,views.py中代码如下:

  from django.shortcuts import render
  def index(request): # 注意此处定义的是函数
    if request.method == 'POST':
      print('method is :' + request.method)
    elif request.method == 'GET':
      print('method is :' + request.method)
    return render(request, 'index.html')
2、CBV

  CBV(class base views),就是在视图里使用类处理请求,view.py中代码如下:

  from django.views import View

  class LoginView(View):   # 类要继承View,类中函数名必须小写
    def get(self, request):
      print('method is :' + request.method)
      return render(request, 'index.html')
    def post(self, request):
      print('method is :' + request.method)
      return render(request, 'index.html')
3、CBV使用

1)路径url的配置

  顾名知义,CBV就是通过类的方法来调用,我们在url中配置为如下路径

  path('index/', views.LoginView.as_view())

  这里的LoginView是一个class 类,LoginView中的View不是必须的。一般约定成俗,会加一个View。要想使用此方法,这个路径后面还得必须有一个as_view(),这是必须的固定格式。

2)views.py里面函数的格式

  在views里面配置类,需要导入一个模块View,并且使配置类继承它,如下代码:

  from django.views import View
  # 这里必须要继承View这个类,只有继承了,对应url那里的as_view()才会有这个方法
  class UserView(View):
    def get(self, request): # get请求时执行
      return HttpResponse('cbv-get')     def post(self, request):
      return HttpResponse('cbv-post') # post请求时执行

  注意:get和post的方法名,必须是小写。因为在源码中,使用了request.method.lower(),通过反射来找到类中的方法!详情请参考下面的内容

3)CBV匹配原理

  这里通过查看View的源码,可以看到里面会有很多种提交方法

  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

  使用ajax的时候这些方法都是可以使用的。

  这种根据url来匹配方法的是通过反射方法(getattr)来做的。请求过来后先走dispatch这个方法,这个方法存在View类中。

  def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:
      handler = getattr(self, request.method.lower(),self.http_method_not_allowed)
    else:
      handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)
  request.method.lower()

  将请求方式变成小写。通过反射来找到类中对应的方法!

  所有的框架,本质都是通过请求方式,反射不同的函数!

  所以CBV的本质,实际还是用的FBV,只不过了类封装而已!

4)定制dispatch

  如果需要批量对方法(例如get,post等方法)做一些操作的时候,这里我们可以手动写一个dispatch,这个dispatch就和装饰器的效果一样。因为请求来的时候总是先走的dispatch,如下代码:

  from django.views import View
  class LoginView(View):
    def dispatch(self, request, *args, **kwargs):
      print('操作前的代码...')
      obj = super(LoginView, self).dispatch(request, *args, **kwargs)
      print('操作后的代码...')
      return obj # 这里一定要记得return     def get(self, request)
      return render(request, 'login.html') # 发送到login.html     def post(self, request):
      return HttpResponse('cbv-post')   

  这次我们再通过浏览器访问的时候,发现不管get或者post方法,都会走print代码。

4、分析下面一段CBV代码报错原因
  from django.views import View
  class LoginView(View):
    def dispatch(self, request, *args, **kwargs):
      print('dispatch...')
      super().dispatch(request, *args, **kwargs)     def get(self, request)
      print('get方法...')
      return HttpResponse('cbv-get')     def post(self, request):
      print('post方法...')
      return HttpResponse('cbv-post')

Django - 自定义分页、FBV和CBV的更多相关文章

  1. django中的FBV和CBV

    django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...

  2. Django自定义分页并保存搜索条件

    Django自定义分页并保存搜索条件 1.自定义分页组件pagination.py import copy class Pagination: def __init__(self, current_p ...

  3. django 自定义分页,网址存储缓存,CBV

    1. 通过切片控制分页 自定义分页: from django.shortcuts import render # Create your views here. from app01.models i ...

  4. django基础之FBV与CBV,ajax序列化补充,Form表单

    目录: FBV与CBV ajax序列化补充 Form表单(一) 一.FBV与CBV 1.什么是FBV.CBV? django书写view时,支持两种格式写法,FBV(function bases vi ...

  5. Django自定义分页、bottle、Flask

    一.使用django实现之定义分页 1.自定义分页在django模板语言中,通过a标签实现; 2.前段a标签使用<a href="/user_list/?page=1"> ...

  6. Django 自定义分页类

    分页类代码: class Page(object): ''' 自定义分页类 可以实现Django ORM数据的的分页展示 输出HTML代码: 使用说明: from utils import mypag ...

  7. Django—自定义分页

    分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该显示在页面上的数据在数据库表中的起始位置. 确定分页需求: 1. 每页显示的数据条数 2. 每页显示页号链接数 3. 上一页 ...

  8. Django——自定义分页(可调用)

    1.view from django.shortcuts import render,HttpResponse # Create your views here. from app01.models ...

  9. django中的FBV和CBV??

    django中请求处理方式有2种:FBV 和 CBV 一.FBV FBV(function base views) 就是在视图里使用函数处理请求. 看代码: urls.py from django.c ...

随机推荐

  1. ubuntu 13.10使用fcitx输入法

    ubuntu 13.10使用fcitx输入法 2013-10-19 20:15:57 标签:fcitx ubuntu 13.10 五笔拼音输入法 原创作品,允许转载,转载时请务必以超链接形式标明文章 ...

  2. nyoj 460 项链 (区间dp)

    项链 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子, ...

  3. 李洪强iOS开发之Xcode快捷键

    14个Xcode中常用的快捷键操作   在Xcode 6中有许多快捷键的设定可以使得你的编程工作更为高效,对于在代码文件中快速导航.定位Bug以及新增应用特性都是极有效的. 当然,你戳进这篇文章的目的 ...

  4. RabbitMQ学习之:(一)初识、概念及心得

    因为网上有一篇很好的RMQ的入门帖子http://lostechies.com/derekgreer/tag/rabbitmq/,所以我就不多说了,就说说我目前看了该作者1~5章后,自己的心得.(所以 ...

  5. lua工具库penlight--06数据(二)

    词法扫描 虽然 Lua 的字符串模式匹配是非常强大,但需要更强大的东西.pl.lexer.scan可以提供标记字符串,按标记机分类数字.字符串等. > lua -lpl Lua 5.1.4  C ...

  6. 在oschina添加了x3dom的索引

    http://www.x3dom.org/ http://www.oschina.net/p/x3dom x3dom的思路非常优秀并且可行,借助于WebGL的春风,将X3D带到了死而复生的境地.

  7. vs的快捷键包含部分代码的自动生成

    VS2010 快捷键 全屏:Shift+Alt+Enter注释选定内容:Ctrl+E+C/Crtr+E+U代码格式化:ctrl+E+F VS2008 使用小技巧——快捷键1. 怎样调整代码排版的格式? ...

  8. Gabor变换、Gabor滤波器

    D.Gabor 1946年提出 窗口Fourier变换,为了由信号的Fourier变换提取局部信息,引入了时间局部化的窗函数. 由于窗口Fourier变换只依赖于部分时间的信号,所以,现在窗口Four ...

  9. 【转】JavaScript和Java的区别

    虽然JavaScript与Java有紧密的联系,但却是两个公司开发的不同的两个产品.      Java是SUN公司推出的新一代面向对象的程序设计语言,特别适合于Internet 应用程序开发:而Ja ...

  10. ADO访问Oracle数据库,连接异常(Unknown error 0x800a0e7a)

    ADO访问Oracle数据库,连接异常(Unknown error 0x800a0e7a) 代码如下:执行Open过程中出现异常,信息为Unknown error 0x800a0e7a  C++ Co ...