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

发布于 2024-07-26 10:02:55 字数 804 浏览 6 评论 0原文

我正在编写一个 mixin,它可以让我的模型轻松转换为深层值字典(有点像 .values(),但遍历关系)。 定义这些的最干净的地方似乎是在模型本身中,a 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

整个堆栈跟踪 这里

现在,我想我可以在我的 mixin 中精心重写它,但是有没有更优雅的方式来存储这些信息?

I'm writing a mixin which will allow my Models to be easily translated into a deep dict of values (kind of like .values(), but traversing relationships). The cleanest place to do the definitions of these seems to be in the models themselves, a 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'
    }
}

However, Django complains about my including this in class Meta with:

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

(entire stack trace here)

Now, I suppose I could elaborately override this in my mixin, but is there a more elegant way of storing this information?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦明 2024-08-02 10:02:56

我不知道什么是优雅,但一种实用的方法是:

import django.db.models.options as options

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

显然,如果 Django 添加了自己的“schema”属性,这就会崩溃。 但是,嘿,这是一个想法......您总是可以选择一个不太可能发生冲突的属性名称。

I don't know about elegant, but one pragmatic way is:

import django.db.models.options as options

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

Obviously, this would break if Django ever added a 'schema' attribute of its own. But hey, it's a thought...you could always pick an attribute name which is less likely to clash.

放手` 2024-08-02 10:02:56

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

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

    class MyPrefixMeta:
        my_value = "Abc"

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

Not a direct answer, but I did not like the idea of adding it in every model where I need it to the options, so I did:

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

    class MyPrefixMeta:
        my_value = "Abc"

You could even put this to a abstract model and validate the set class properties in __init__ function or do things like adding a _myprefix_meta property to the model. So you had your own meta class.

哎呦我呸! 2024-08-02 10:02:56

这对我来说适用于在 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)

我希望这能解决问题。

This works for me for setting extra fields in meta for a Django model.

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)

This exclude_logging field can be accessed as below.

class CustomModel(models.Model):

    objects = UpdateManager()

    class Meta:
        abstract = True

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

I hope this solves the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文