在 Django 2.0 中按字段值排序

3
这个问题类似于 django 排序,但我无法使任何解决方案起作用。
我有以下模型:
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" alt="">
  </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 %}

如何对我的结果进行排序?

1
你使用哪个“视图”来呈现响应?最好在视图中准备好这个有序查询集。 - Willem Van Onsem
2个回答

7
基本上有两种方法可以实现这个目的:
  1. 视图 中定义排序; 或者
  2. 模型 中定义一个 默认 排序(可以用另一种排序方式覆盖它)。

如果模型具有合理的排序方式(例如,在特定的方式下对查询集进行排序非常合适,而只有偶尔需要使用其他方式),通常会使用最后一种选项。

视图 中的排序

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

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

def some_view(request):
    my_products = Product.objects.all()<b>.order_by('-votes_total')</b>
    return render(request, 'my_template.html', {<b>'my_products': my_products</b>})

然后我们可以使用变量'my_products',并对其进行迭代:
{% extends 'base.html' %}

{% block content %}

{% for product in <b>my_products</b> %}
<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" alt="">
  </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:
        <b>ordering = ['-votes_total']</b>

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

但请注意,我们每个模型只能定义一个这样的排序方式,因此做出某个决定不能基于特定视图进行指定。如果您想“覆盖”排序,则需要在查询集上使用order_by


3
您需要在视图中对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)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接