在Django 2.0中按字段值排序

时间:2018-05-28 16:50:42

标签: django django-models

此问题与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" 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 %}

如何对结果进行排序?

2 个答案:

答案 0 :(得分:2)

您应该在视图中对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)。

答案 1 :(得分:1)

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

  1. 视图中定义排序;或
  2. 模型中定义默认排序(可以使用其他排序覆盖的排序)。
  3. 如果模型具有敏感(固有)排序,则通常使用最后一个选项(例如,以某种方式对查询集进行排序是非常合理的,并且仅偶尔以另一种方式排序)。

    视图

    中排序

    我们可以使用查询集的.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" 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 %}

    模型

    上定义排序

    如果某个排序从模型角度看是非常合理的,我们也可以在模型本身中封装排序。我们使用属性的ordering类的Meta属性指定它。如果我们希望例如默认按降序顺序中的投票数排序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