orphans相关知识
-
jquery 弹出框 <span class="Apple-style-span" microsoft="" yahei';="" font-size:="" 20px;="" font-style:="" normal;="" font-variant:="" font-weight:="" letter-spacing:="" line-height:="" 30px;="" orphans:="" 2;="" text-align:="" left;="" text-indent:="" 0px;
-
Linux命令执行顺序控制与管道、cut 、grep 、wc 、sort本篇内容:顺序执行、选择执行、管道、cut 命令、grep 命令、wc 命令、sort 命令等,高效率使用 Linux 的技巧。顺序执行多条命令通常情况下,我们每次只能在终端输入一条命令,按下回车执行,执行完成后,我们再输入第二条命令,然后再按回车执行……,当有时候我们会一次输入多条命令,这个时候的执行过程有是如何的呢?<pre class="cpp" style="margin: 0px 0px 24px; padding: 0px 16px; border-radius: 8px; background: rgb(240, 240, 240); color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-inden
-
谈谈这几个常见的多线程面试题创建线程有几种不同的方式?你喜欢哪一种?为什么?有三种方式可以用来创建线程:继承Thread类实现Runnable接口应用程序可以使用Executor框架来创建线程池实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。概括的解释下线程的几种可用状态。新建( new ):新创建了一个线程对象;可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取CPU的使用权;运行( running ):可运行状态( runnable )的线程获得了CPU时间片( timeslice ) ,执行程序代码;阻塞( block ):阻塞状态是指线程因为某种原因放弃了CPU 使用权,也即让出了 CPU timeslice ,暂时停止运行。直到线程进入可
-
《前端之路》之 webpack 4.0+ 的应用构建一、版本当前 webpack 版本 : v4.18.0webpack -v// 4.18.0同之前的版本不一样的地方是需要 全局安装 webpack-cliwebpack-cli -v// 3.1.0思考这个 webpack-cli 是真的有用么? 其实对于我来讲感觉很鸡肋,虽然它是出现是为了让我webpack 零配置化,但就目前 webpack-cli 的体验来讲,还是比较鸡肋,在实际的开发过程中,我还是比较喜欢 diy ,这样自由的折腾方式, 零配置,就意味着你要为 高度定制化作出牺牲。这让我想起了之前面试很多前端开发的时候,其实就是一个很简单的问题,如何搭建一个最简单的 webpack 的开发架构,JS 压缩一下, LESS 预编译一下, CSS 压缩一下。这类,很多习惯了用 vue-cli 的同学就懵逼了,因为他们认为 架构就是用别人的东西,但实际的开发中,出于业务需求的需要,我们的架构需要更加多的灵活性和高度可定制化性。 所以这才是写这篇文章的 出发点。二、
orphans相关课程
orphans相关教程
- 2.2 MultipleObjectMixin 这个 Mixin 是用来帮助视图处理多个对象的,如列表展示,分页查询都是在这里。这也是 ListView 视图类的核心所在。来看看源代码里面关于这个 Mixin 的属性和方法:属性:allow_empty: 是否允许对象列表为空,默认为 True;queryset:对象的查询集;model:关联的模型;paginate_by: 分页大小;paginate_orphans: 这个比较有意思,需要通过代码来详细解释下其含义。# 源码位置 django/core/paginator.pyclass Paginator: def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True): self.object_list = object_list self._check_object_list_is_ordered() self.per_page = int(per_page) self.orphans = int(orphans) self.allow_empty_first_page = allow_empty_first_page # ... def page(self, number): """Return a Page object for the given 1-based page number.""" number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page #这里可以看出 self.orphans 的含义 if top + self.orphans >= self.count: top = self.count return self._get_page(self.object_list[bottom:top], number, self) # ...上面的 page() 方法是根据传入的 number 获取第几页数据,每页的大小由 per_page 属性确定。我们在前面的 TemplateView 中的分页实例中知道,想要获取第几页的数据,可以按照如下公式:# 起始位置,number从1开始start = (number - 1) * per_page# 结束位置,不包括end end = number * per_page# 另一种简单写法 end = start + per_page# 数据切片,取第number页数据object_list[start:end]orphans 属性的含义就体现在下面两行代码中:if top + self.orphans >= self.count: top = self.count这里的含义是,如果计算出的下一页的位置加上这个 orphans 属性的值大于等于对象的总数,也就是说下一页的数据如果少于 orphans 的值,那么当前这一页需要把下一页剩余的元素都选中。举个例子,假设与102个数据,现在按照每页展示10条数据,当我展示到第10页是,元素的位置应该是 90-99,作为切片的话,应该是[90:100],即bottom=90, top=100 。假设我设置orphans=3,那么有100 + 3 > 102,即最后一页数目少于3个,因此通过上面的逻辑判断后,top=102,此时显示的列表切片为 [90:102]。context_object_name:这个设置上下文中对象列表名称。我们来翻看源代码,查看这个属性的含义,如下。# 源码位置:django/views/generic/list.pyclass MultipleObjectMixin(ContextMixin): # ... def get_context_object_name(self, object_list): """Get the name of the item to be used in the context.""" if self.context_object_name: return self.context_object_name elif hasattr(object_list, 'model'): return '%s_list' % object_list.model._meta.model_name else: return None def get_context_data(self, *, object_list=None, **kwargs): """Get the context for this view.""" queryset = object_list if object_list is not None else self.object_list page_size = self.get_paginate_by(queryset) context_object_name = self.get_context_object_name(queryset) if page_size: paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size) context = { 'paginator': paginator, 'page_obj': page, 'is_paginated': is_paginated, 'object_list': queryset } else: context = { 'paginator': None, 'page_obj': None, 'is_paginated': False, 'object_list': queryset } if context_object_name is not None: context[context_object_name] = queryset context.update(kwargs) return super().get_context_data(**context) # ... 查看源码可以知道,这个属性不设置也是有默认值的(注意:只有在 object_list 没设置,或者不是 QuerySet 时,才返回 None 值)。通过 get_context_data() 代码中的这样一条语句:context[context_object_name] = queryset这样,在模板文件中,我们就可以使用 context_object_name 变量来循环显示我们的对象列表了。paginator_class:用于分页的类,这种写法让 django 的分页变得可扩展,我们可以提供这样的分页类来替换掉 Django 中原有的分页机制,从而实现我们自己的分页控制。这种做法在可扩展的模式中用的非常多,不过需要仔细研读分页的源码,需要定义的属性和方法才能替换官方的分页类。page_kwarg: 查询页号的 key 值。这个是指,查询的页号是从获取参数的这个 key 值中取出来的,可以是在 URLConf 配置中设定,也可以通过 GET 请求带参数传递过来。来看看源码里面如何使用这个属性的,具体如下。# 源码路径:django/views/generic/list.pyclass MultipleObjectMixin(ContextMixin): # ... def paginate_queryset(self, queryset, page_size): # ... page_kwarg = self.page_kwarg page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1 # ... # ...ordering:这个属性是用来设置查询列表的排序,可以放入多个排序字段。比如 ordering = ['name'],表示结果集按照 name 字段从小到大排序,如果想按照倒序的顺序,直接用 ordering = ['-name'] 即可。方法:get_queryset():返回视图的对象列表:class MultipleObjectMixin(ContextMixin): # ... def get_queryset(self): """ Return the list of items for this view. The return value must be an iterable and may be an instance of `QuerySet` in which case `QuerySet` specific behavior will be enabled. """ if self.queryset is not None: queryset = self.queryset if isinstance(queryset, QuerySet): queryset = queryset.all() elif self.model is not None: queryset = self.model._default_manager.all() else: raise ImproperlyConfigured( "%(cls)s is missing a QuerySet. Define " "%(cls)s.model, %(cls)s.queryset, or override " "%(cls)s.get_queryset()." % { 'cls': self.__class__.__name__ } ) ordering = self.get_ordering() if ordering: if isinstance(ordering, str): ordering = (ordering,) queryset = queryset.order_by(*ordering) return queryset在这里,代码逻辑也是非常清楚的。首先是需要理解 Django 的 ORM 操作。在一开始设置了 queryset 属性时,如果直接是 QuerySet 的实例,则会将用 .all() 将所有的数据取出来,得到 queryset 并返回。当然这里看代码,不设置 queryset 也是可以的,设置好关联的模型属性 model,然后通过模型的默认 manager 调用 .all() 方法也能实现同样的目标。最后,在这里还使用了 ordering 的属性值,如果有设置,则直接用 QuerySet 的 .ordering() 方法。几个简单的获取属性值得方法,如下:get_ordering():获取排序字段;get_paginate_by(): 获取分页大小;get_paginator():实例化分页对象,关联 paginator_class 属性值;get_paginate_orphans(): 获取 paginate_orphans 这个属性值;get_allow_empty():获取 allow_empty 这个属性值;get_context_object_name():处理 context_object_name 这个属性值;class MultipleObjectMixin(ContextMixin): # ... def get_ordering(self): """Return the field or fields to use for ordering the queryset.""" return self.ordering # ... def get_paginate_by(self, queryset): """ Get the number of items to paginate by, or ``None`` for no pagination. """ return self.paginate_by def get_paginator(self, queryset, per_page, orphans=0, allow_empty_first_page=True, **kwargs): """Return an instance of the paginator for this view.""" return self.paginator_class( queryset, per_page, orphans=orphans, allow_empty_first_page=allow_empty_first_page, **kwargs) def get_paginate_orphans(self): """ Return the maximum number of orphans extend the last page by when paginating. """ return self.paginate_orphans def get_allow_empty(self): """ Return ``True`` if the view should display empty lists and ``False`` if a 404 should be raised instead. """ return self.allow_empty def get_context_object_name(self, object_list): """Get the name of the item to be used in the context.""" if self.context_object_name: return self.context_object_name elif hasattr(object_list, 'model'): return '%s_list' % object_list.model._meta.model_name else: return None # ...paginate_queryset():获取分页数据以及分页信息。该函数会被 get_context_data() 方法调用生成上下文数据,用于填充模板中的变量内容。该部分源码会结合 get_context_data() 方法一起在下一小节中详细介绍到;get_context_data():获取渲染模板的上下文数据,也即分页列表元素、分页信息等,在下一部分内容会详细介绍该函数中的内容。
- 2.3 BaseListView 讲完上面的 MultipleObjectMixin 对象,ListView 视图的基本功能其实就分析完了。 BaseListView 类继承了 View 和 MultipleObjectMixin,并多添加了一个 get() 方法。这也是 ListView 能直接处理 get 请求的原因。实验1中的第一个报错也是源自这里:self.object_list = self.get_queryset() 。只有定义了 queryset 或者 model属性时,才能正常执行下去。class BaseListView(MultipleObjectMixin, View): """A base view for displaying a list of objects.""" def get(self, request, *args, **kwargs): # 获取对象列表 self.object_list = self.get_queryset() # 是否设置允许为空 allow_empty = self.get_allow_empty() if not allow_empty: # 下面的if用于判断数据是否为空,然后相应设置is_empty值 if self.get_paginate_by(self.object_list) is not None and hasattr(self.object_list, 'exists'): is_empty = not self.object_list.exists() else: is_empty = not self.object_list # 在不许为空的条件中,如果为空直接抛出404异常 if is_empty: raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.") % { 'class_name': self.__class__.__name__, }) # 获取分页相关的数据 context = self.get_context_data() # 渲染模板并返回 return self.render_to_response(context)可以看到,这段代码执行的过程非常简单,很容易能看懂,我已经在上面做好了简单的注释。这段代码中最重要的部分就在这一句中: context = self.get_context_data()。这段代码是要获取相应的分页数据结果,然后调用 self.render_to_response(context) 来返回经过渲染的模板文件,最后就是我们看到的那个会员列表页面。self.get_context_data() 方法就是上面的 Mixin 提供的,函数源码如下: def get_context_data(self, *, object_list=None, **kwargs): """Get the context for this view.""" # 获取对象列表 queryset = object_list if object_list is not None else self.object_list # 获取分页大小 page_size = self.get_paginate_by(queryset) # 获取context_object_name,我们实验2中设置的就是members,对应着模板中的变量 context_object_name = self.get_context_object_name(queryset) if page_size: # 核心的处理就是这一句,根据指定的分页大小对数据集进行分析,返回分页的对象列表,分页信息、是否分页等 paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size) context = { 'paginator': paginator, 'page_obj': page, 'is_paginated': is_paginated, 'object_list': queryset } else: # 没有设置分页大小,就是获取全部数据,不进行分页 context = { 'paginator': None, 'page_obj': None, 'is_paginated': False, 'object_list': queryset } # 设置模板中对象列表变量的数据 if context_object_name is not None: context[context_object_name] = queryset # context中再添加额外传入的数据 context.update(kwargs) # 最后调用父类的get_context_data()方法并返回 return super().get_context_data(**context)上面的获取上下文数据的代码也比较简单,有分页大小就调用self.paginate_queryset() 方法查询分页数,没有分页大小就使用全部对象列表,然后构造 context 值,最后调用父类的 get_context_data() 方法并返回。可以看到,整个获取上下文数据的最核心处理就是 self.paginate_queryset() 这个方法了。它也是由上面介绍的那个 Mixin 提供的,代码如下: def paginate_queryset(self, queryset, page_size): """Paginate the queryset, if needed.""" # 核心处理就是这一句 paginator = self.get_paginator( queryset, page_size, orphans=self.get_paginate_orphans(), allow_empty_first_page=self.get_allow_empty()) # 查询第几页的key值,默认是"page" page_kwarg = self.page_kwarg # 第几页的值会从kwargs或者GET请求中获取,对应的key就是上面的page_kwarg,没有就默认为1 page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1 try: # 会强制转成int page_number = int(page) except ValueError: # 当强制转换异常时,处理逻辑也很清晰 if page == 'last': page_number = paginator.num_pages else: raise Http404(_("Page is not 'last', nor can it be converted to an int.")) try: # 生成对应的page实例。一切正常时,返回我们所需要的数据,否则抛出异常 page = paginator.page(page_number) return (paginator, page, page.object_list, page.has_other_pages()) except InvalidPage as e: raise Http404(_('Invalid page (%(page_number)s): %(message)s') % { 'page_number': page_number, 'message': str(e) })当这部分代码能看懂时,前面实验2部分的整个内部逻辑,你差不多也就弄清楚了。虽然我们看着只需要配置几个属性,但是在 Django 内部是替我们做了许多工作的,如果这部分工作并不是你想要的,这时候,就需要依据你自己的业务逻辑重写相应的函数了。如果能掌握整个 ListView 视图的执行流程,在继承它的时候就会感到胸有成竹,有错了就去根据错误提示追踪下源码,这样就不会再碰到错误时,不知道从何下手。所以,阅读源码是在学习 Django 这样的 Web 框架时,非常重要的一个技能,而且很多关于 Django 的功能和用法我们都可以通过源码来获取。最后,我们来看看 ListView 的代码,其实就是单纯继承前面那个处理多个对象的 Mixin 和这个 BaseListView:class ListView(MultipleObjectTemplateResponseMixin, BaseListView): """ Render some list of objects, set by `self.model` or `self.queryset`. `self.queryset` can actually be any iterable of items, not just a queryset. """
- 11-1 风险管理的那些事儿 各方向通用的项目管理实战
- flex 弹性盒子布局 零基础学习,探索减少CSS3提高性能的奥秘
- 并发编程简介 零基础入门 Java 并发原理
- Kotlin 基本数据类型 Kotlin 是安卓开发的官方语言
orphans相关搜索
-
oauth
object
object c
objective
objective c
objective c基础教程
objective c教程
objectivec
office visio 2003
offsetof
offsetparent
offset函数
okhttp
on on
on time
onbeforeunload
onblur
onclick
oncontextmenu
online