小技巧:在模型中指定文章的排序

为了让文章(Post)按发布时间逆序排列,即最新发表的文章排在文章列表的最前面,我们对返回的文章列表进行了排序,即各个视图函数中都有类似于 Post.objects.all().order_by('-created_time') 这样的代码,这导致了很多重复。因为只要是返回的文章列表,基本都是逆序排列的,因此我们可以在 Post 模型中指定 Post 的自然排序方式。

Django 允许我们在 models.Model 的子类里定义一个 Meta 的内部类,这个内部类通过指定一些属性来规定这个类该有的一些特性,例如在这里我们要指定 Post 的排序方式。首先看到 Post 的代码:

blog/models.py

class Post(models.Model):
    ...
    created_time = models.DateTimeField()
    ...

    def __str__(self):
        ...

    def get_absolute_url(self):
        ...

现在在 Post 类的内部定义一个 Meta 类,并指定排序属性:

blog/models.py

class Post(models.Model):
    ...
    created_time = models.DateTimeField()
    ...

    def __str__(self):
        ...

    def get_absolute_url(self):
        ...

    class Meta:
        ordering = ['-created_time']

ordering 属性用来指定文章排序方式,['-created_time'] 指定了依据哪个属性的值进行排序,这里指定为按照文章发布时间排序,且负号表示逆序排列。列表中可以用多个项,比如 ordering = ['-created_time', 'title'] ,那么首先依据 created_time 排序,如果 created_time 相同,则再依据 title 排序。这样指定以后所有返回的文章列表都会自动按照 Meta 中指定的顺序排序,因此可以删掉视图函数中对文章列表中返回结果进行排序的代码了。

blog/views.py

def category(request, pk):
    # 记得在开始部分导入 Category 类
    cate = get_object_or_404(Category, pk=pk)
    # 下面这行删除 .order_by('-created_time')
    post_list = Post.objects.filter(category=cate)
    return render(request, 'blog/index.html', context={'post_list': post_list})

如此刷新你的页面,所有返回的文章列表都会自动按照 Meta 中指定的顺序排序。但是有时候我们更多是按照自己喜欢的一些排序,比如“自定义排序”。按时间写出来的文章进行排序不一定就是我们喜欢的排序。因此该方法只做介绍,不建议都增加。