2

我有一个关于如何在模型实例启动时动态设置模型属性的问题。

我正在使用带有原生 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() 设置实例属性,但是在 Django 文档中强烈建议不要重写模型的init方法。

有没有其他方法可以实现这一目标?任何帮助表示赞赏。

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

4

2 回答 2

1

您可以简单地__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]语法更明确。

于 2017-05-10T11:06:41.483 回答
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)
于 2017-05-10T11:03:48.957 回答