ChatGPT解决这个技术问题 Extra ChatGPT

Django 的嵌套 Meta 类是如何工作的?

我正在使用 Django,它允许人们使用 class Meta 向类添加额外的参数。

class FooModel(models.Model):
    ...
    class Meta:
        ...

我在 Python 的文档中发现的唯一内容是:

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

但是,我认为这不是一回事。

标题询问了 Python 元,但问题似乎询问了 Django 元——你问的是哪一个?
@ckhan 由于荒谬的决定(IMO)调用嵌套类“Meta”而感到困惑,这非常具有误导性;对于初学者,关于 Python 的元类,以及对于从未见过它的更有经验的用户,关于它的先验目的(而不是使用类属性或真正的元类)

S
Saeed

你在问一个关于两个不同事情的问题:

Django 模型中的元内部类:这只是一个带有一些选项(元数据)附加到模型的类容器。它定义了诸如可用权限、关联的数据库表名称、模型是否是抽象的、名称的单复数版本等。简短的解释在这里:Django docs: Models: Meta options 可用的元选项列表在这里: Django 文档:模型元选项 对于最新版本的 Django:Django 文档:模型元选项 Python 中的元类:最好的描述在这里:Python 中的元类是什么?


这两件事有关系吗?即,Django 的 Meta 内部类是否会阻止您使用 Python 的内置元类功能?
@nnyby:有两件事在这两个概念之间建立了关系:许多用户的名称和混淆(正如 OP 在原始问题中所说的那样)。我相信解决这个常见的混淆是这个话题的显着优势。你不同意吗?
什么是“类容器”?我以为我理解了 Python 中的 classcontainer data types,但我不明白你提到的“类容器”概念是什么?
t
theUtherSide

扩展上面 Tadeck 的 Django 答案,在 Django 中使用 'class Meta:' 也只是普通的 Python。

内部类是类实例之间共享数据的方便命名空间(因此“元数据”的名称为 Meta,但您可以随意称呼它)。虽然在 Django 中它通常是只读配置的东西,但没有什么可以阻止你改变它:

In [1]: class Foo(object):
   ...:     class Meta:
   ...:         metaVal = 1
   ...:         
In [2]: f1 = Foo()
In [3]: f2 = Foo()
In [4]: f1.Meta.metaVal
Out[4]: 1
In [5]: f2.Meta.metaVal = 2
In [6]: f1.Meta.metaVal
Out[6]: 2
In [7]: Foo.Meta.metaVal
Out[7]: 2

您也可以直接在 Django 中探索它,例如:

In [1]: from django.contrib.auth.models import User
In [2]: User.Meta
Out[2]: django.contrib.auth.models.Meta
In [3]: User.Meta.__dict__
Out[3]: 
{'__doc__': None,
 '__module__': 'django.contrib.auth.models',
 'abstract': False,
 'verbose_name': <django.utils.functional.__proxy__ at 0x26a6610>,
 'verbose_name_plural': <django.utils.functional.__proxy__ at 0x26a6650>}

但是,在 Django 中,您更可能想要探索 _meta 属性,它是在创建模型时由模型 metaclass 创建的 Options 对象。在那里您可以找到所有 Django 类的“元”信息。在 Django 中,Meta 仅用于将信息传递到创建 _meta Options 对象的过程中。


这不适用于用户定义的模型: >>>from myapp.models import MyModel >>>MyModel.Meta Traceback(最后一次调用):文件“”,第 1 行,在 中 AttributeError:类型对象“MyModel”没有属性“元”
您需要下划线,例如 MyUser.objects.get(pk=1)._meta
是的,但这不会访问模型类的内部 Meta 类。访问该模型实例的 _meta 选项......似乎没有一种方法可以访问内部 Meta 类本身。我的用例是以 MyModelProxy 可以继承 MyModel 的内部 Meta 类的方式从 MyModel 继承代理 MyModelProxy 类。
我不完全清楚模型的“内部元类”是什么意思,但您始终可以直接使用实例的类,例如 type(MyUser.objects.get(pk=1)).Meta
“类实例之间共享数据的方便命名空间” 那行为我做了。
A
Amber

Django 的 Model 类专门处理具有名为 Meta 的属性,它是一个类。这不是一般的 Python 事物。

Python 元类完全不同。


我认为您的答案不够清楚 - 您能否详细说明 Meta 类的工作原理?我相信OP专门询问了这一点。
j
jhrr

声称 Django 模型的 Meta 和元类“完全不同”的答案是误导性的答案。

Django模型类对象的构造,也就是说代表类定义本身的对象(是的,类也是对象),确实是由一个叫做ModelBase的元类控制的,而你可以see that code here

ModelBase 所做的一件事是在每个 Django 模型上创建 _meta 属性,其中包含验证机制、字段详细信息、保存逻辑等。在此操作期间,模型的内部 Meta 类中指定的内容被读取并在该过程中使用。

因此,虽然是的,但在某种意义上 Meta 和元类是不同的“事物”,但在 Django 模型构建的机制中,它们是密切相关的;了解它们如何协同工作将同时加深您对两者的洞察力。

这可能是一个有用的信息来源,可以更好地理解 Django 模型如何使用元类。

https://code.djangoproject.com/wiki/DevModelCreation

如果您想更好地了解对象的一般工作方式,这也可能会有所帮助。

https://docs.python.org/3/reference/datamodel.html


s
shiva

内部元类文档:

django 模型元数据的这个文档是“任何不是字段的东西”,例如排序选项 (ordering), database table name (db_table), or human-readable singular and plural names (verbose_name and verbose_name_plural)。不需要,将 Meta 类添加到模型是完全可选的。 https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options


R
Rishi Chhabra

在 Django 中,它充当配置类并将配置数据保存在一个地方!


H
HassanSh__3571619

类 Meta 是你的代码逻辑中你的 model.fields 与你的 form.widgets 相遇的地方。因此,在 Class Meta() 下,您可以在模型字段和您希望在表单中拥有的不同小部件之间创建链接。