感谢这篇文章,我可以轻松地在Django视图中通过查询进行计数和分组:
Django equivalent for count and group by
我在我的应用程序中所做的是显示我的数据库中可用于某个国家/地区的硬币类型和面值的列表,因此来自英国的硬币可能具有“1个最小值”或“6便士”的面值。 face_value
是6,currency_type
是“便士”,存储在相关表格中。
我在视图中有以下代码可以让我获得90%的代码:
def coins_by_country(request, country_name):
country = Country.objects.get(name=country_name)
coin_values = Collectible.objects.filter(country=country.id, type=1).extra(select={'count': 'count(1)'},
order_by=['-count']).values('count', 'face_value', 'currency_type')
coin_values.query.group_by = ['currency_type_id', 'face_value']
return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )
currency_type_id
作为存储在外键字段中的数字(即4)出现。我想要做的是检索它作为查询的一部分引用的实际对象(货币模型,所以我可以在我的模板中获取Currency.name字段)。
最好的方法是什么?
答案 0 :(得分:2)
您无法使用values()
执行此操作。但是没有必要使用它 - 你可以只获取实际的Collectible
个对象,每个对象都有一个currency_type
属性,它将成为相关的链接对象。
正如justinhamade所说,使用select_related()
将有助于减少数据库查询的数量。
把它放在一起,你得到:
coin_values = Collectible.objects.filter(country=country.id,
type=1).extra(
select={'count': 'count(1)'},
order_by=['-count']
).select_related()
答案 1 :(得分:1)
select_related()
让我非常接近,但它希望我将我选择的每个字段添加到group_by
子句中。
所以我尝试在values()
之后添加select_related()
。不行。然后我尝试了查询的不同位置中的每个的各种排列。关闭,但不完全。
我最终“懦弱”并且只使用原始SQL,因为我已经知道如何编写SQL查询。
def coins_by_country(request, country_name):
country = get_object_or_404(Country, name=country_name)
cursor = connection.cursor()
cursor.execute('SELECT count(*), face_value, collection_currency.name FROM collection_collectible, collection_currency WHERE collection_collectible.currency_type_id = collection_currency.id AND country_id=%s AND type=1 group by face_value, collection_currency.name', [country.id] )
coin_values = cursor.fetchall()
return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )
如果有一种方法可以用Django查询集语言来表达那个确切的查询,我很想知道。我想,一个带有计数和两列分组的SQL连接并不是非常罕见的,所以如果没有一个干净的方法,我会感到惊讶。
答案 2 :(得分:0)
您是否尝试过select_related()http://docs.djangoproject.com/en/dev/ref/models/querysets/#id4
我经常使用它似乎工作得很好然后你可以去coin_values.currency.name。
另外我不认为你需要在你的过滤器中做country = country.id,只有country = country但是我不确定除了打字之外还有什么区别。