django - 在 Django 2.0 中按字段值排序
问题描述
这个问题就像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 %}
如何对结果进行排序?
解决方案
基本上有两种方法可以做到这一点:
- 在视图中定义排序;或者
- 在模型中定义一个默认排序(可以被另一个排序覆盖的排序)。
如果模型具有有意义的(固有的)排序,则通常使用最后一个选项(例如,以某种方式对查询集进行排序是非常合乎逻辑的,并且只是偶尔以另一种方式)。
在视图中排序
.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
集上使用用户。
推荐阅读
- xtext - 如何使 XTEXT 模板不区分大小写?
- python - Python AES 解密 struct TypeError
- ios - 在 ios 中使用 ARKit 显示演练
- sql-server - 阶乘函数错误 - 超出最大存储过程、函数、触发器或视图嵌套级别
- c# - 如何使用 fileupload 将图像存储到项目外部的另一个文件夹?
- r - 使用 [r] 通过 POST 请求从 Internet 获取数据的问题
- php - 在 php OOP 中使用 $this 可以访问不定义公共属性
- citrus-framework - Citrusframework - 包括标准的 TestNG 测试类
- python - Python - 以结构化方式向类动态添加新函数
- java - Android kotlin / JAVA - jloop AsyncHttpClient 检查外部文件是否存在