Du kan använda jsonb_extract_path_text via en Func objekt som ett alternativ till fälttransformen:
Pet.annotate(dinner=Func(
F('data'), Value('diet'), Value('dinner'),
function='jsonb_extract_path_text')) \
.values('dinner') \
.annotate(total=Count('dinner'))
Anledningen till att fältet transformerar data__diet__dinner fails är ett fel inom Django när du går djupare än bara en nivå in i json-strukturen och använd GROUP BY i SQL. Den första nivån (name , animal , diet ) borde fungera bra.
Anledningen verkar vara att för kapslade transformationer ändrar Django SQL-syntaxen som används, och byter från ett enstaka värde till en lista för att ange sökvägen till json-strukturen.
Det här är syntaxen som används för icke-kapslade json-transformationer (=första nivån):
"appname_pet"."data" -> 'diet'
Och det här är syntaxen som används för kapslade transformationer (djupare än första nivån):
"appname_pet"."data" #> ARRAY['diet', 'dinner']
När Django konstruerar frågan kväver Django den listan medan han utarbetar den nödvändiga GROUP BY klausuler. Detta verkar inte vara en oundviklig begränsning; stödet för transformeringar är ganska nytt, och det här är möjligen en av de kinks som inte har lösts ännu. Så om du öppnar en Django-biljett
, detta kanske bara fungerar några versioner längre fram.