Django的QuerySets酷毙了!
在本文中我将解释一下QuerySets是什么,它是如何工作的(如果你对它已经熟悉了,你可以直接跳到第二部分),我认为如果可以的话你应该总是返回QuerySets对象,下面让我来谈谈如何做。
QuerySets很酷
QuerySet,本质上是一个给定的模型的对象列表。我说“列表”而不是“组”或更正式的“集合”因为它是有序的。事实上,你可能已经熟悉如何获得QuerySets,因为这就是你调用variousBook.objects.XXX()方法后得到的对象。例如,考虑下面的语句:
Book.objects.all()
all()返回的就是Book实例的一个QuerySet,它正好包括allBookinstances,下面的其他调用你可能已经知道:
# Return all books published since 1990Book.objects.filter(year_published__gt=1990) # Return all books *not* written by Richard DawkinsBook.objects.exclude(author='Richard Dawkins') # Return all books, ordered by author name, then# chronologically, with the newer ones first.Book.objects.order_by('author', '-year_published')
关于 QuerySet s最酷的是,由于这些函数操作、返回的都是一个QuerySet,你可以把他们链起来:
# Return all book published after 1990, except for# ones written by Richard Dawkins. Order them by# author name, then chronologically, with the newer# ones first.Book.objects.filter(year_published__gt=1990) / .exclude(author='Richard Dawkins') / .order_by('author', '-year_published')
而且这并不是全部的,它更快!
在内部,一个QuerySet可以被构造、过滤、切片及像普通变量那样在没有实际数据库查询的情况下随便传递,在评估处理完QuerySet前不产生数据库活动。
所有我们确认了QuerySets很酷,不是么?
尽可能的返回QuerySets
我最近曾在一个Django应用中用一个模型来表示树(数据结构,不是圣诞装饰)。这意味着每一个实例在树上都有一个指向它父节点的链接。它看起来像这样:
class Node(models.Model): parent = models.ForeignKey(to='self', null=True, blank=True) value = models.IntegerField() def __unicode__(self): return 'Node #{}'.format(self.id) def get_ancestors(self): if self.parent is None: return [] return [self.parent] + self.parent.get_ancestors()
这工作的相当好。麻烦的是,我不得不添加另一种方法,get_larger_ancestors,它应该返回所有值大于当前节点的的父节点。这是我能实现这个:
def get_larger_ancestors(self): ancestors = self.get_ancestors() return [node for node in ancestors if node.value > self.value]
问题是,我基本上会在名单上审查两次——Django一次,我自己一次。这让我考虑到-如果get_ancestors返回QuerySet而不是列表会怎样呢?我可以这样做:
新闻热点
疑难解答