Django:基于JSONField动态设置模型实例属性
Django: Dynamically set model instance attributes based on JSONField
我有一个关于如何在启动模型实例时动态设置模型属性的问题。
我正在使用带有本机 PostgreSQL JSONField 的简单模型:
from django.db import models
from django.contrib.postgres.fields import JSONField
class Booking(models.Model):
data = JSONField(blank=False, encoder=DjangoJSONEncoder)
在实例化模型时,是否有任何方法可以根据存储在 'data' 字段中的值来设置模型实例的属性?
我希望能够做到这一点:
from .models import Booking
b = Booking.objects.create(data={'foo':'bar'})
b.foo # this should yield 'bar'
我最初的想法是覆盖模型的 init 方法并使用 setattr() 设置实例属性,但覆盖模型的 init Django 文档中强烈建议不要使用该方法。
还有其他方法可以实现吗?感谢任何帮助。
PS:我知道我可以像这样在模型实例上访问存储在 'data' 中的值:booking.data['foo'],所以这不是我在找什么。
如果你真的想这样做,你可以覆盖getattr
方法。
class Booking(models.Model):
def __getattr__(self, attr):
if attr in self.data:
return self.data[attr]
else:
return super(Booking, self).__getattr__(attr)
您可以简单地在您的模型中实现 __getattr__
挂钩,即:
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)
)
但除非您真的确信您的 json 内容将始终具有相同的结构,否则我建议您不要这样做 - 使用简单的 instance.data[key]
语法更为明确。
我有一个关于如何在启动模型实例时动态设置模型属性的问题。
我正在使用带有本机 PostgreSQL JSONField 的简单模型:
from django.db import models
from django.contrib.postgres.fields import JSONField
class Booking(models.Model):
data = JSONField(blank=False, encoder=DjangoJSONEncoder)
在实例化模型时,是否有任何方法可以根据存储在 'data' 字段中的值来设置模型实例的属性?
我希望能够做到这一点:
from .models import Booking
b = Booking.objects.create(data={'foo':'bar'})
b.foo # this should yield 'bar'
我最初的想法是覆盖模型的 init 方法并使用 setattr() 设置实例属性,但覆盖模型的 init Django 文档中强烈建议不要使用该方法。
还有其他方法可以实现吗?感谢任何帮助。
PS:我知道我可以像这样在模型实例上访问存储在 'data' 中的值:booking.data['foo'],所以这不是我在找什么。
如果你真的想这样做,你可以覆盖getattr
方法。
class Booking(models.Model):
def __getattr__(self, attr):
if attr in self.data:
return self.data[attr]
else:
return super(Booking, self).__getattr__(attr)
您可以简单地在您的模型中实现 __getattr__
挂钩,即:
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)
)
但除非您真的确信您的 json 内容将始终具有相同的结构,否则我建议您不要这样做 - 使用简单的 instance.data[key]
语法更为明确。