Happy Ahmad
Happy Ahmad

Reputation: 1087

Python Django: Annotating a same name with a database field

I need to annotate something that has to be named 'id' that is the same as the primary key of the table 'id'. The final output should be an array of dictionaries. I know that I can annotate with another name like 'id_for_tree' and then after using values() to make the dictionaries and change the key in a loop. Something like:

item_list = MyTable.objects.annotate(id_for_tree=Concat(F('id'), F('Code'), output_field=CharField())).values('Name', 'id_for_tree')
for any_item in item_list:
    any_item['id'] = any_item.pop('id_for_tree')

It's clear that this solution does not have a good performance. How can I get rid of the

"The annotation 'id' conflicts with a field on the model"

exception by discarding the previous 'id' and annotate a new 'id'?

Upvotes: 3

Views: 8609

Answers (1)

PyPingu
PyPingu

Reputation: 1747

"something that has to be named 'id'"

Why?

Anyway, that aside, have you tried simply moving the call to values ahead of the call to annotate?

i.e.

item_list = MyTable.objects.values('Name').annotate(id=Concat(F('id'), F('Code'), output_field=CharField()))

This is predicated on the Name field also being unique.

EDIT: If the Name field is not unique, then you can do it with an extra call to values and annotate. i.e.

item_list = MyTable.objects.values(
    'Name', 'id'
    ).annotate(
    id_dummy=Concat(F('id'), F('Code'), output_field=CharField())
    ).values(
    'id_dummy', 
    'Name'
    ).annotate(
     id=F('id_dummy')
    )

EDIT from question owner: Finally, I used this code to avoid unintentionally group_by:

item_list = MyTable.objects.annotate(
    OriginalId=F('id')
    ).values(
      'Name', 
     'OriginalId'
    ).annotate(
      id=Concat(F('id'), F('Code'), output_field=CharField()
    ))

Upvotes: 7

Related Questions