博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django - 自定义分页、FBV和CBV
阅读量:2240 次
发布时间:2019-05-09

本文共 7032 字,大约阅读时间需要 23 分钟。

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

"""分页组件使用示例:    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 = '
  • 首页
  • ' % (self.params.urlencode()) page_html_list.append(first_page) if self.current_page_num <= 1: prev_page = '
  • 上一页
  • ' # 第一页的上一页禁用 else: self.params["page"] = self.current_page_num - 1 prev_page = '
  • 上一页
  • ' % (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 = '
  • %s
  • ' %(self.params.urlencode(), i) else: temp = '
  • %s
  • ' % (self.params.urlencode(), i,) page_html_list.append(temp) if self.current_page_num >= self.all_pager: next_page = '
  • 下一页
  • ' # 最后一页的下一页禁用 else: self.params["page"] = self.current_page_num + 1 next_page = '
  • 下一页
  • ' % (self.params.urlencode()) page_html_list.append(next_page) self.params["page"] = self.all_pager last_page = '
  • 尾页
  • ' % (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')

     

    转载于:https://www.cnblogs.com/li-li/p/9926134.html

    你可能感兴趣的文章
    解决问题之 MySQL慢查询日志设置
    查看>>
    contOS6 部署 lnmp、FTP、composer、ThinkPHP5、docker详细步骤
    查看>>
    TP5.1模板布局中遇到的坑,配置完不生效解决办法
    查看>>
    PHPstudy中遇到的坑No input file specified,以及传到linux环境下遇到的坑,模板文件不存在
    查看>>
    TP5.1事务操作和TP5事务回滚操作多表
    查看>>
    composer install或composer update 或 composer require phpoffice/phpexcel 失败解决办法
    查看>>
    TP5.1项目从windows的Apache服务迁移到linux的Nginx服务需要注意几点。
    查看>>
    win10安装软件 打开时报错 找不到 msvcp120.dll
    查看>>
    PHPunit+Xdebug代码覆盖率以及遇到的问题汇总
    查看>>
    PHPUnit安装及使用
    查看>>
    PHP项目用xhprof性能分析(安装及应用实例)
    查看>>
    composer安装YII
    查看>>
    Sublime text3快捷键演示
    查看>>
    sublime text3 快捷键修改
    查看>>
    关于PHP几点建议
    查看>>
    硬盘的接口、协议
    查看>>
    VLAN与子网划分区别
    查看>>
    Cisco Packet Tracer教程
    查看>>
    02. 交换机的基本配置和管理
    查看>>
    03. 交换机的Telnet远程登陆配置
    查看>>