'Replace django results/blanket manipulate data

I need to be able to globally replace certain data in django results and perform operations on it.

I already have a custom manager doing exclusions based on another database eg CRMData.filtered_obj which works fine however I have instances requiring certain things to be grouped, I then need to perform totals/counts of the new grouping for example I get a result using annotate(Count(name)) eg:

Pizza 20
Beer 5
Tea 3
Nerds 2

And for example I need to combine Pizza and Beer so the list becomes:

Beer & Pizza 25
Tea 3
Nerds 2
Banana 1

And the list must now be populated with the next highest number.

I've attempted doing something like:

CRMData.objects.extra(select={'name1': 'case name where "Beer" OR "Pizza" then "Beer & Pizza" else name'})

Which outputs a result with the extra column but I cannot perform

CRMData.objects.extra(select={'name1': 'case name where "Beer" OR "Pizza" then "Beer & Pizza" else name'}).values('name1').annotate(Count('name1'))

As I get a:

Cannot resolve keyword 'name1' into field

I've tried a few different things like adding .group_by() to the end but I still get the same error.

Ideally I want to be able to transact using the queryset methods as there's a lot of pre-existing code built around it, the goal is to add this as a custom manager method that preceeds other methods but I'm not sure if this is possible.

I've toyed with the idea of placing the results into a panda dataframe and using that but if anyone has any suggestions if this isn't possible I'd be grateful although it will mean a lot of rewriting of code.



Solution 1:[1]

After some research and advice from the django users mailing list I've been advised that django's ORM doesn't support such a function.

A solution I came up with hypothetically would be be to use django to generate the query and replace the column name and run the query raw eg.

a = CRMData.objects.filter(log_type='Request').query

SELECT `"TABLE_NAME"`.`"Log_Number "`, `"TABLE_NAME"`.`"First_Name"`, 
`"TABLE_NAME"`.`"Incident_Date"`, `"TABLE_NAME"`.`"Item_Description"`, 
`"TABLE_NAME"`.`"Problem_Code"`, `"TABLE_NAME"`.`"Call_type"`, 
`"TABLE_NAME"`.`"Log_Severity"`, `"TABLE_NAME"`.`"Log_Status"`, 
`"TABLE_NAME"`.`"Owner"`, `"TABLE_NAME"`.`"Group"`, `"TABLE_NAME"`.`"Log_Summary"`, 
`"TABLE_NAME"`.`"Created_By"`, `"TABLE_NAME"`.`"USER_NAME"`, 
`"TABLE_NAME"`.`"LAST_UPDATE_DATE"`, `"TABLE_NAME"`.`"LAST_UPDATED_BY"`, 
`"TABLE_NAME"`.`"LAST_UPDATED_BY_USERNAME"` FROM `"TABLE_NAME"` WHERE 
`"TABLE_NAME"`.`"Call_type"` = Request 

This provides the raw query so now we can replace the relevant column with a case eg.

new_query = a.replace('`"TABLE_NAME"`.`"Problem_Code"`', 
'CASE `"TABLE_NAME"`.`"Problem_Code"` 
WHEN "value" then "new value" 
ELSE `"TABLE_NAME"`.`"Problem_Code"` 
END')

You can then run

instance = CRM.objects.raw(new_query)

To return the results.

It's also possible to process this in Python which is viable but would take a bit more work on Python's part. There's probably a more efficient way of doing this but that's all I have at this stage.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 illuzian