将属性添加到Django Model的Meta类中

时间:2009-07-06 18:08:22

标签: python django django-models metadata

我正在写一个mixin,它可以让我的模型很容易被翻译成一个深刻的价值观(有点像.values(),但是遍历关系)。对这些进行定义的最干净的地方似乎是模型本身,la:

class Person(models.Model, DeepValues):
    name = models.CharField(blank=True, max_length=100)
    tribe = models.ForeignKey('Tribes')

    class Meta:
        schema = {
            'name' : str,
            'tribe' : {
                'name' : str
            }
        }

Person.objects.all().deep_values() => {
    'name' : 'Andrey Fedorov',
    'tribe' : {
        'name' : 'Mohicans'
    }
}

但是,Django抱怨我在class Meta中将其包括在内:

TypeError: 'class Meta' got invalid attribute(s): schema

(整个堆栈跟踪here

现在,我想我可以在我的mixin中巧妙地覆盖它,但是有更优雅的方式来存储这些信息吗?

3 个答案:

答案 0 :(得分:49)

我不知道优雅,但一种务实的方式是:

import django.db.models.options as options

options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('schema',)

显然,如果Django添加了自己的'schema'属性,这将会破坏。但是,嘿,这是一个想法......你总是可以选择一个不太可能发生冲突的属性名称。

答案 1 :(得分:0)

不是直接的答案,但是我不喜欢在需要的选项中将其添加到每个模型中的想法,所以我做到了:

class MyModel(models.Model):
    
    class Meta:
        ordering = ["myfield"]

    class MyPrefixMeta:
        my_value = "Abc"

您甚至可以将其放入抽象模型中,并在__init__函数中验证设置的类属性,或执行向模型中添加_myprefix_meta属性的操作。所以你有自己的元类。

答案 2 :(得分:0)

这对我来说适用于在 Django 模型的元数据中设置额外的字段。

class Vendor(CustomModel):

    def __init__(self, *args, **kwargs):
        cls = self.__class__
        meta = getattr(cls, '_meta', None)
        setattr(meta, 'exclude_logging', ["otp", "is_otp_verified"])
        super().__init__(*args, **kwargs)

exclude_logging 字段可按如下方式访问。

class CustomModel(models.Model):

    objects = UpdateManager()

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        print(self._meta.exclude_logging)

我希望这能解决问题。