I have a ReportTemplate
table with a JSONField that contains a formset. As usual, the formset looks something like this:
{
'settings-0-a': 10021,
'settings-0-b': 'Locale',
'settings-0-c': '...',
'settings-TOTAL_FORMS': 1,
'settings-INITIAL_FORMS': 1,
'settings-MAX_NUM_FORMS': 1000,
'settings-MIN_NUM_FORMS': 0
}
I’d like to query this in the database. To get to the raw data, I worked up the following SQL query:
SELECT id,
CASE (split_part(key, '-', 3)) WHEN '' THEN 'management' ELSE split_part(key, '-', 2) END AS form,
CASE (split_part(key, '-', 3)) WHEN '' THEN split_part(key, '-', 2) ELSE split_part(key, '-', 3) END AS field,
value from (
SELECT rt.id, (jsonb_each(rt.settings)).* from app_reporttemplate as rt
) AS x(id,key,value)
which I can use like this:
$ ./manage.py dbshell
foo=# SELECT id, ...as above... where id=10000011;
id | form | field | value
-------+------------+---------------+---------------------------------
10001 | 0 | id | 10021
10001 | 0 | name | "Locale"
10001 | 0 | type | "paiyroll.report.SettingString"
10001 | 0 | regex | ""
10001 | 0 | value | "en_GB"
10001 | management | TOTAL_FORMS | 1
10001 | 0 | max_length | 80
10001 | 0 | description | "Locale, e.g. en_US, de_GE"
10001 | management | INITIAL_FORMS | 1
10001 | management | MAX_NUM_FORMS | 1000
10001 | management | MIN_NUM_FORMS | 0
(11 rows)
I tried to wrap this in a Raw SQL query:
$ ./manage.py shell
In [27]: for row in models.ReportTemplate.objects.raw("SELECT id,...query as above..."):
...: print(row.id, row.form, row.field, row.value)
This produces the expected output from the annotations for form
, field
and value
. But of course, the output of a raw query cannot be used to .filter()
or anything much else.
So, my question is how else might one approach this problem and end up with something that is more centered in the ORM?