DJANGO:排序套装

时间:2017-07-23 05:27:02

标签: python django sorting foreign-keys

我有这个模型(简化):

#models.py

class Expression(models.Model):
    text = models.CharField(max_length=254)

class Country(models.Model):
    name = models.CharField(max_length=100)

class Definition(models.Model):
    expression = models.ForeignKey(Expression)
    country = models.ForeignKey(Country)
    text = models.CharField(max_length=254)

class Vote(models.Model):
    definition = models.ForeignKey(Definition)

这个观点

#views.py

def index(request):
    expressions = Expression.objects.all()
    return render(request, 'expression_index.html', { 'expressions':expressions)

因此它将显示最后10个创建的表达式。

然后在模板中我有这个:

#index.html

{% for expression in expressions %}
    {{ expression }}
    {% for definition in expression.definition_set.all %}
        <ul>
            <li>{{ definition }}</li>
        </ul>
    {% endfor %}
{% endfor %}

每个定义都有几张选票。 每一次投票都是一行,所以我们可以这样做:

definition.votes_set.count()

如何实现这样显示:

按字母顺序排列每个国家/地区的最高定义。每个国家/地区只有一个定义。

让我们说德国有两个表达“A”的定义,而丹麦对同一表达有三个定义,它只会显示两个定义:投票最多的定义。

我希望我有意义。

由于

2 个答案:

答案 0 :(得分:0)

我认为这样的事情应该有用(未经测试)

from django.db.models import Count
{{ expression.definition_set.annotate(Count('votes_set')) }}
{% for definition in expression.definition_set.order_by('country','votes_set__count') %}

答案 1 :(得分:0)

此查询集将按国家/地区的字母顺序排序,然后从每个国家/地区的最高投票定义到最少。

expression = Expression.objects.get(text__exact="A")
definitions = Definition.objects.filter(expression=expression).annotate(num_votes=Count('vote')).order_by("country__name", "-num_votes")

如果我尝试只保留每个国家/地区的最高定义,并在查询集的末尾设置.distinct(“country”),则会抛出此错误:

NotImplementedError at  annotate() + distinct(fields) is not implemented.

另一种解决方案是:

import operator

expression = Expression.objects.get(text__exact="A")

# Get top definitions sorted by num of votes and convert the values to list.
top_definitions = list(Definition.objects.filter(expression=expression).annotate(num_votes=Count('vote')).order_by("num_votes").values("id", "country", "country__name", "expression", "text", "num_votes"))

# Remove dublicate countries and leave the only the top voted definition.
definitions = list({v['country']: v for v in top_definitions}.values())

# Sort alphabetically by country.
definitions.sort(key=operator.itemgetter('country__name'))

return render(request, 'expression_index.html', {'definitions': definitions, 'expression': expression})

模板:

<h1>{{ expression.text }}</h1>
<ul>
    {% for definition in definitions %}
            <li>{{ definition.country__name }} - {{ definition.text }} - {{ definition.num_votes }}</li>
    {% endfor %}
</ul>