如何解决Django Order QuerySet by Min Value from Child Table
我正在努力在 Django 中创建一个特定的复杂查询。 我正在使用 pagination 在索引页面上显示蛋糕列表。我想按不同的属性对它们进行排序。下面是我的索引页截图。
Name (A-Z)
和 Name (Z-A)
是通过简单地按“name”或“-name”对 Cake 查询集进行排序来实现的,我从页面顶部的表单中将其作为 POST 获取。
cakes_list = Cake.objects.all().order_by('name')
但是我正在努力按最低价格订购查询集。
每个蛋糕都有不同的尺寸和不同的价格(蛋糕之间的尺寸和价格不同)。它们存储在 Dimension
中,外键指向它们所属的 Cake
。
我想找出每个蛋糕最便宜的选项,并根据它(最低价格升序和降序)订购我在分页中使用的蛋糕列表。
我还创建了一个方法 from_price
来返回那个蛋糕的价格。我在模板中使用它来显示每个蛋糕的名称和最低价格。但我似乎无法将其实施到我的排序中。
我很感激有关如何创建查询或类似问题的帮助,让我可以根据每个蛋糕的最低价格对所有蛋糕进行排序。我只是在学习 Django,所以我目前的实现可能并不理想。
保险库/models.py:
class Cake(models.Model):
name = models.CharField(max_length=200)
def from_price(self):
temp = self.dimension_set.aggregate(Min('price')).get('price__min')
if not temp:
temp = 0
return temp
class Dimension(models.Model):
cake = models.ForeignKey(Cake,on_delete=models.CASCADE)
dimension = models.CharField(max_length=50)
price = models.DecimalField(max_digits=6,decimal_places=2)
保险库/views.py
def index(request):
#from the form on the index page
order_by = request.POST.get('order_by')
if not order_by:
order_by = 'name'
cakes_list = Cake.objects.all().order_by(order_by)
paginator = Paginator(cakes_list,5)
page_number = request.GET.get('page',1)
page_obj = paginator.get_page(page_number)
return render(request,'vault/index.html',{'page_obj': page_obj,'order_by': order_by})
Vault/templates/vault/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{# Form for cake sorting dropdown #}
<form action="{% url 'vault:index' %}" method="post">
{% csrf_token %}
<label for="order_by">Order by:</label>
<select name="order_by" id="order_by">
<option {% if order_by == "name" %} selected="selected" {% endif %} value="name">Name (A-Z)</option>
<option {% if order_by == "-name" %} selected="selected" {% endif %} value="-name">Name (Z-A)</option>
{% comment %}
New options for ordering by price
<option {% if order_by == "" %} selected="selected" {% endif %} value="name">Price from (Low to High)</option>
<option {% if order_by == "" %} selected="selected" {% endif %} value="-name">Price from (High to Low)</option>
{% endcomment %}
</select>
<input type="submit" value="Select">
</form>
{# Code for printing the list of cakes #}
{% if page_obj %}
<ul>
{% for cake in page_obj %}
<li>
<a href="{% url 'vault:detail' cake.id %}">
{{ cake.name }}
{% if cake.from_price %}
- from £{{ cake.from_price|floatformat:'2' }}
{% endif %}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>No cakes are available</p>
{% endif %}
{# Code for the pagination navigation elements #}
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
</span>
</div>
</body>
</html>
解决方法
在这样排序之前尝试使用注释:
cakes_list = Cake.objects.annotate(
max_price=Max('dimension__price'),).order_by('max_price')
,
如果您需要每个 Cake
记录的最低价格值,那么最简单的方法可能是使用 subquery:
from django.db.models import OuterRef,Subquery
sub_q = Dimension.objects.filter(cake=OuterRef('id')).order_by('price')
qs = Cake.objects.annotate(min_price=Subquery(sub_q.values('prize')[:1]).order_by('min_price')
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。