在 Django 2.0 中按字段值排序

Posted

技术标签:

【中文标题】在 Django 2.0 中按字段值排序【英文标题】:Sort by field value in Django 2.0 【发布时间】:2018-11-07 07:15:22 【问题描述】:

这个问题类似于django sorting,但我无法让任何解决方案发挥作用。

我有以下型号:

from django.db import models
from django.contrib.auth.models import User

class Product(models.Model):

    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField()
    body = models.TextField()
    url = models.TextField()
    image = models.ImageField(upload_to='images/')
    icon = models.ImageField(upload_to='images/')
    votes_total = models.IntegerField(default=1)
    hunter = models.ForeignKey(User, on_delete=models.CASCADE)

    def summary(self):
        return self.body[:50]

    def pub_date_pretty(self):
        return self.pub_date.strftime('%b %e %Y')

    def __str__(self):
        return self.title

我想按 votes_total 排序,这样当我遍历数据库时,结果按 votes_total 排序。

% extends 'base.html' %

% block content %

% for product in products.all %
<div class="row pt-3">
  <div class="col-2" onclick="window.location='% url 'detail' product.id %';" style="cursor:pointer">
    <img src=" product.icon.url " class="img-fluid" >
  </div>
  <div class="col-6" onclick="window.location='% url 'detail' product.id %';" style="cursor:pointer">
    <h1> product.title </h1>
    <p> product.summary </p>
  </div>
  <div class="col-4" onclick="window.location='% url 'detail' product.id %';" style="cursor:pointer">
    <a href="javascript:document.getElementById('upvote product.id ').submit()"><button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Upvote  product.votes_total </button></a>
  </div>
</div>

<form id="upvote product.id " method="POST" action="% url 'upvote' product.id %">
  % csrf_token %
  <input type="hidden">
</form>
% endfor %

% endblock %

如何对结果进行排序?

【问题讨论】:

您使用什么view 来呈现响应?你最好在视图中准备这个有序的查询集。 【参考方案1】:

您应该对视图中的queryset 进行排序并将其传递给模板。用于按升序排序

return render(request, template_name,
    'products': Product.objects.all().order_by('votes_total')
)

降序排序:

return render(request, template_name,
    'products': Product.objects.all().order_by('-votes_total')
)

您应该在模板中使用products(不是 products.all)。

【讨论】:

【参考方案2】:

基本上有两种方法可以做到这一点:

    视图中定义排序;或 在模型中定义一个默认排序(可以被另一个排序覆盖的排序)。

如果模型具有合理(固有)排序,则通常使用最后一个选项(例如,以某种方式对查询集进行排序是非常合乎逻辑的,并且只是偶尔以另一种方式排序)。

视图中排序

我们可以使用查询集的.order_by(..) 函数对查询集进行排序。该函数采用任意数量的参数:指定列名的字符串。如果列名以减号 (-) 为前缀,则表示我们按降序排序。

例如我们可以定义一个视图:

def some_view(request):
    my_products = Product.objects.all().order_by('-votes_total')
    return render(request, 'my_template.html', 'my_products': my_products)

然后我们可以使用这个'my_products' 变量,并对其进行迭代:

% extends 'base.html' %

% block content %

% for product in my_products %
<div class="row pt-3">
  <div class="col-2" onclick="window.location='% url 'detail' product.id %';" style="cursor:pointer">
    <img src=" product.icon.url " class="img-fluid" >
  </div>
  <div class="col-6" onclick="window.location='% url 'detail' product.id %';" style="cursor:pointer">
    <h1> product.title </h1>
    <p> product.summary </p>
  </div>
  <div class="col-4" onclick="window.location='% url 'detail' product.id %';" style="cursor:pointer">
    <a href="javascript:document.getElementById('upvote product.id ').submit()"><button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Upvote  product.votes_total </button></a>
  </div>
</div>

<form id="upvote product.id " method="POST" action="% url 'upvote' product.id %">
  % csrf_token %
  <input type="hidden">
</form>
% endfor %

% endblock %

模型上定义排序

如果某个排序从模型的角度来看是非常合乎逻辑的,我们也可以将排序封装在模型本身中。我们使用属性的Meta 类的ordering 属性来指定它。例如,如果我们希望默认以 降序 的投票数对Product.objects.all() 进行排序,我们可以这样写:

class Product(models.Model):

    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField()
    body = models.TextField()
    url = models.TextField()
    image = models.ImageField(upload_to='images/')
    icon = models.ImageField(upload_to='images/')
    votes_total = models.IntegerField(default=1)
    hunter = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        ordering = ['-votes_total']

所以现在我们仍然可以在模板中访问Product.objects.all,并且项目会自动排序。

但是请注意,我们只能为每个模型定义一个这样的排序,从而做出特定的决定,不能基于特定的视图来指定。如果您想“覆盖”排序,您需要在查询集上使用order_by

【讨论】:

以上是关于在 Django 2.0 中按字段值排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中按计算字段复杂排序?

在 django 中按模型字段的子字符串对对象进行排序

在 Solr 中按特定顺序按多个字段排序

如何使用extjs4.1在网格中按降序对带有连字符的浮点值进行排序

使用mongoose在mongodb中按升序和降序对多个字段进行排序

在django模板中按降序对相关项目进行排序