I have a question on how to set model attributes dynamically when model instances are initiated.
I am using a simple model with a native PostgreSQL JSONField:
from django.db import models
from django.contrib.postgres.fields import JSONField
class Booking(models.Model):
data = JSONField(blank=False, encoder=DjangoJSONEncoder)
Is there any way to set attributes on the model instance based on the values stored in the 'data' field when the model is instantiated?
I want to be able to do this:
from .models import Booking
b = Booking.objects.create(data={'foo':'bar'})
b.foo # this should yield 'bar'
My initial thought was to override the model's init method and set the instance attributes with setattr(), but overriding a model's init method is strongly discouraged in the Django docs.
Is there any other way to achieve this? Any help is appreciated.
PS: I know that I can access the values stored in 'data' on a model instance like so: booking.data['foo'], so this is not what I am looking for.
You could simply implement the __getattr__
hook in your model, ie:
class Booking(models.Model):
# ...
def __getattr__(self, name):
try:
return self.data[name]
except KeyError:
try:
return super(Boooking, self).__getattr__(name)
except AttributeError:
raise AttributeError(
"object %s has no attribute '%s'" % (type(self).__name__, name)
)
but unless you are really confident that your json content will always have the same structure I would advise against it - using the plain instance.data[key]
syntax is more explicit.