Vous pouvez utiliser jsonb_extract_path_text via une Func objet comme alternative à la transformation de champ :
Pet.annotate(dinner=Func(
F('data'), Value('diet'), Value('dinner'),
function='jsonb_extract_path_text')) \
.values('dinner') \
.annotate(total=Count('dinner'))
La raison pour laquelle le champ transforme data__diet__dinner
échoue est une erreur dans Django lorsque vous allez plus loin qu'un seul niveau dans la structure json et utilisez GROUP BY
dans le SQL. Le premier niveau (name
, animal
, diet
) devrait fonctionner correctement.
La raison semble être que pour les transformations imbriquées, Django modifie la syntaxe SQL utilisée, passant d'une valeur unique à une liste pour spécifier le chemin dans la structure json.
Voici la syntaxe utilisée pour les transformations json non imbriquées (=premier niveau) :
"appname_pet"."data" -> 'diet'
Et voici la syntaxe utilisée pour les transformations imbriquées (plus profondes que le premier niveau) :
"appname_pet"."data" #> ARRAY['diet', 'dinner']
Lors de la construction de la requête, Django s'étouffe sur cette liste tout en travaillant sur le GROUP BY
requis clauses. Cela ne semble pas être une restriction inévitable; la prise en charge des transformations est assez nouvelle, et c'est peut-être l'un des problèmes qui n'ont pas encore été résolus. Donc si vous ouvrez un ticket Django
, cela pourrait ne fonctionner que quelques versions plus tard.