在Django中,如何在extra().values()调用中获取相关对象?

3
感谢这篇文章,我能够在Django视图中轻松地进行计数和分组查询: Django equivalent for count and group by 我的应用程序正在显示一个国家数据库中可用的硬币类型和面值列表,因此来自英国的硬币可能具有“1 farthing”或“6 pence”的面值。 face_value是6,“currency_type”是“pence”,存储在相关表中。
我在我的视图中有以下代码,让我完成了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 模型),以便在模板中获取 Currency.name 字段。

最好的方法是什么?

3个回答

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

select_related() 让我接近了,但它要求我将选择的每个字段添加到 group_by 子句中。

所以我尝试在 select_related() 后面附加 values()。不行。然后我尝试在查询的不同位置对它们进行各种排列组合。接近了,但还不够。

最终我“退缩”并使用原始 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 queryset语言来表达这个确切的查询,我会很感兴趣。我想象中,使用两个列进行计数和分组的SQL连接并不是非常罕见,所以如果没有一种简洁的方法,我会感到惊讶。

0
你尝试过使用select_related()吗?http://docs.djangoproject.com/en/dev/ref/models/querysets/#id4 我经常使用它,似乎效果很好,然后你就可以使用coin_values.currency.name。
另外,我认为在你的筛选器中不需要使用country=country.id,只需要使用country=country即可,但我不确定这样做有什么区别,除了少打几个字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接