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] 语法更为明确。