Django:基于JSONField动态设置模型实例属性

时间:2017-05-10 10:52:16

标签: python django postgresql django-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)

有没有办法根据存储在'数据中的值设置模型实例上的属性?模型实例化时的字段?

我希望能够做到这一点:

from .models import Booking

b = Booking.objects.create(data={'foo':'bar'})
b.foo # this should yield 'bar'

我最初的想法是覆盖模型的 init 方法,并使用setattr()设置实例属性,但覆盖模型的 init 在Django文档中强烈建议不要使用该方法。

还有其他方法可以达到这个目的吗?任何帮助表示赞赏。

PS:我知道我可以访问存储在'数据'中的值在这样的模型实例上:booking.data [' foo'],所以这不是我要找的。

2 个答案:

答案 0 :(得分:0)

如果您真的想这样做,可以覆盖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)

答案 1 :(得分:0)

您可以在模型中简单地实现__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]语法更明确。