Reputation: 1253
I am trying to dynamically add an attribute to at runtime using the following snippets of code:
...
for appellation in queryset:
if appellation.id in used_id_set:
appellation.is_used_flag()
print(appellation.is_used)
# prints true as expected
else:
appellation.is_not_used_flag()
first = queryset.first()
print(first.is_used)
# prints AttributeError: 'Appellation' object has no attribute 'is_used'
...
def is_used_flag(self):
self.is_used = True
def is_not_used_flag(self):
self.is_used = False
Why does it work correctly when in the loop but when I try to retrieve the attribute from an instance after it does not work? I have run into the same issue using setattr, appellation.is_used = True
and modifying __dict__
. Also is there a better way to do this?
I have referenced these posts:
Why can't you add attributes to object in python? I do have a dict but it does not seem to "persist" after the loop
How to assign a new class attribute via __dict__? Same issue as mentioned above
Dynamically defining instance fields in Python classes Same as above
Since both answers mention similar things, I should clarify what my intentions are. I do not want to actually persist the value in the DB. I just want to serialize it and use it in the front end.
Upvotes: 0
Views: 169
Reputation: 71
The Queryset API in django (often) returns other querysets, which are in turn evaluated by accessing the database. By doing queryset.first()
you're executing another database call, where your attributes have not been yet set.
If you need to save this is_used
flag between querysets (persist the change), I suggest you add a BooleanField on your model, or perhaps find another way to do what you want, as in memory attributes will not get returned by using the queryset API.
Upvotes: 1
Reputation: 347
If you want the change to persist you will need to call self.save()
after setting is_used
, assuming that is_used
is a field on the Appellation
model.
models.py
from django.db import models
class Appellation(models.Model):
# ... rest of code ...
is_used = models.BooleanField(default=False)
def is_used_flag(self):
self.is_used = True
self.save()
def is_not_used_flag(self):
self.is_used = False
self.save()
Note that Django instances are still Python objects so adding an attribute dynamically will work in the same way, this is why it prints True
as expected in the code you provided.
Upvotes: 0