0

I have a simple dict containing ids with values associated like: {1:True, 2:False}

My model:

class Profile(models.Model):
    user_id = models.IntegerField(unique=True, blank=True, null=True)

I also have a queryset that have the same ids listed above in an atribute named user_id, but I need to add a new field to my objects on queryset with the values from my dict. Lets suppose the field I want to add is called is_admin, so I need to create a field on the object with id 1 on my queryset with the value True.

What I tried to do is:

my_dict= {1:True, 2:False}

queryset = queryset.annotate(
    is_admin=Value(my_dict.get(F("user_id")), output_field=BooleanField())
)

But what happen is that I'm receiving null on is_admin. I tried to do the code below and it works:

queryset = queryset.annotate(
    is_admin=Value(my_dict.get(1), output_field=BooleanField())
)

So I think is something wrong with my use of F expression. I will appreciate any help.

2 Answers2

0

I guess it is not ok to mix non-trivial python code into the query expression, beacause it needs to be translated to raw SQL.

I suggest setting this property after you get the data from DB. Something like this:

results = list(queryset)
for r in results:
  r.is_admin = my_dict.get(r.id, False)

Other alternatives, if you want to use this in multiple places:

  1. create new @property def is_admin(self): return my_dict.get(self.id, False)
  2. add it as a new field for your model
Zeusko
  • 47
  • 1
  • 6
  • This might be of consideration, but depending on the model for 'Value', it should accept a boolean in sql just fine. Creating that object from an object of none will make a null value however. – Gracen Ownby Jan 17 '23 at 13:52
  • But I do not think the query expression will work for this: `my_dict.get(F("user_id"))`. Django would need to somehow translate a python method call to SQL. – Zeusko Jan 17 '23 at 13:57
  • After he creates the object he has to call 'is_admin.save()' Creating objects[link](https://docs.djangoproject.com/en/4.1/topics/db/queries/) – Gracen Ownby Jan 17 '23 at 14:02
0

The problem is that the expression F is used to modify strings while your dictionary keys are integer values. Modify the my_dict.get() value by casting it to an integer using int()

>>> newString = f"{user_id}"
>>> newString
'2'
>>> print(my_dict.get(newString))
None
>>> newInt = int(newString)
>>> print(my_dict.get(newInt))
False
Gracen Ownby
  • 341
  • 1
  • 10