Django的Meta类如何工作?

问题:Django的Meta类如何工作?

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

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

我在Python文档中发现的唯一东西是:

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

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

I am using Django which allows people to add extra parameters to a class by using class Meta.

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

The only thing I found in Python’s documentation was:

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

However, I don’t think this is the same thing.


回答 0

您在问有关两个不同问题的问题:

  1. MetaDjango模型中的内部类

    这只是一个类容器,在模型上附加了一些选项(元数据)。它定义了诸如可用权限,关联的数据库表名称,模型是否抽象,名称的单复数形式等内容。

    简短说明在这里:Django文档:模型:Meta选项

    可用的元选项列表在此处:Django文档:Model Meta options

    对于最新版本的Django:Django docs:Model Meta options

  2. Python中的元类

    最好的描述在这里:Python中的元类什么?

You are asking a question about two different things:

  1. Meta inner class in Django models:

    This is just a class container with some options (metadata) attached to the model. It defines such things as available permissions, associated database table name, whether the model is abstract or not, singular and plural versions of the name etc.

    Short explanation is here: Django docs: Models: Meta options

    List of available meta options is here: Django docs: Model Meta options

    For latest version of Django: Django docs: Model Meta options

  2. Metaclass in Python:

    The best description is here: What are metaclasses in Python?


回答 1

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

内部类是在类实例之间共享数据的方便的命名空间(因此,名称为“ metadata”的元数据,但是您可以随意命名)。在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中,您更可能希望探索创建模型时由模型创建_metaOptions对象的属性metaclass。在这里,您将找到所有Django类“元”信息。在Django中,Meta仅用于将信息传递到创建_meta Options对象的过程中。

Extending on Tadeck’s Django answer above, the use of ‘class Meta:’ in Django is just normal Python too.

The internal class is a convenient namespace for shared data among the class instances (hence the name Meta for ‘metadata’ but you can call it anything you like). While in Django it’s generally read-only configuration stuff, there is nothing to stop you changing it:

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

You can explore it in Django directly too e.g:

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>}

However, in Django you are more likely to want to explore the _meta attribute which is an Options object created by the model metaclass when a model is created. That is where you’ll find all of the Django class ‘meta’ information. In Django, Meta is just used to pass information into the process of creating the _meta Options object.


回答 2

Django的Model类专门处理具有名为Metawhich 的属性的类。这不是一般的Python。

Python元类完全不同。

Django’s Model class specifically handles having an attribute named Meta which is a class. It’s not a general Python thing.

Python metaclasses are completely different.


回答 3

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

Django模型类对象(也就是说,代表类定义本身的对象;是的,类也是对象)的构造实际上是由称为的元类控制的ModelBase,您可以在此处看到该代码:

https://github.com/django/django/blob/master/django/db/models/base.py#L61

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

因此,虽然是的,Meta但从某种意义上说,元类是不同的“事物”,但在Django模型构建的机制内,它们是密切相关的;了解它们如何协同工作将一次加深您的见解。

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

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

如果您想更好地了解对象的总体工作原理,这也可能会有所帮助。

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

Answers that claim Django model’s Meta and metaclasses are “completely different” are misleading answers.

The construction of Django model class objects, that is to say the object that stands for the class definition itself (yes, classes are also objects), are indeed controlled by a metaclass called ModelBase, and you can see that code here.

And one of the things that ModelBase does is to create the _meta attribute on every Django model which contains validation machinery, field details, save logic and so forth. During this operation, the stuff that is specified in the model’s inner Meta class is read and used within that process.

So, while yes, in a sense Meta and metaclasses are different ‘things’, within the mechanics of Django model construction they are intimately related; understanding how they work together will deepen your insight into both at once.

This might be a helpful source of information to better understand how Django models employ metaclasses.

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

And this might help too if you want to better understand how objects work in general.

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


回答 4

内部元类文档django Model元数据的文档是“任何不是字段的东西”,例如排序选项(排序),数据库表名称(db_table)或人类可读的单数和复数名称(verbose_name和verbose_name_plural)。不需要任何操作,并且将Meta类添加到模型是完全可选的。 https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options

Inner Meta Class Document This document of django Model metadata is “anything that’s not a field”, such as ordering options (ordering), database table name (db_table), or human-readable singular and plural names (verbose_name and verbose_name_plural). None are required, and adding class Meta to a model is completely optional. https://docs.djangoproject.com/en/dev/topics/db/models/#meta-options


回答 5

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

In Django, it acts as a configuration class and keeps the configuration data in one place!!