Как работает Мета-класс Джанго?

112

Я использую Django, который позволяет людям добавлять дополнительные параметры в класс с помощью class Meta.

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

Единственное, что я нашел в документации Python:

class FooMetaClass(type):
    ...

class FooClass:
    __metaclass__ = FooMetaClass

Однако я не думаю, что это одно и то же.

  • 6
    Название спрашивает о метафоне Python, но кажется, что вопрос о мета Django - какой из них вы спрашиваете?
  • 1
    @ckhan он смущен из-за абсурдного решения (IMO) называть вложенный класс "Meta", что очень вводит в заблуждение; новичкам, о метаклассах Python и более опытным пользователям, которые никогда не видели его, о его назначении априори (вместо использования атрибутов класса или реальных метаклассов)
Теги:
metaclass

4 ответа

144
Лучший ответ

Вы задаете вопрос о двух разных вещах:

  • Meta внутренний класс в моделях Django:

    Это просто контейнер класса с некоторыми параметрами (метаданными), прикрепленными к модели. Он определяет такие вещи, как доступные разрешения, связанное имя таблицы базы данных, является ли модель абстрактной или нет, единственной и множественной версиями имени и т.д.

    Краткое объяснение здесь: Django docs: Модели: Мета-параметры

    Список доступных мета-параметров находится здесь: Django docs: Параметры метаданных Model

  • Метакласс в Python:

    Лучшее описание здесь: Что такое метакласс в Python?

  • 2
    Эти две вещи связаны вообще? то есть, внутренний класс Django Meta мешает вам использовать встроенные в Python функции метакласса?
  • 7
    @nnyby: есть две вещи, которые создают связь между этими двумя понятиями: имя и путаница у многих пользователей (как это было у OP в оригинальном вопросе). Я считаю, что решение этой общей путаницы является существенным преимуществом этого топи. Ты не согласен?
32

Расширение ответа Tadeck Django выше, использование "класса Meta:" в Django - тоже обычный 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, который является объектом Options, созданным метаклассом модели при создании модели. Вот где вы найдете всю информацию о мета-метамерии класса django. В Django Meta просто используется для передачи информации в процесс создания объекта _meta Options.

  • 0
    Это не работает на пользовательских моделях: >>> из myapp.models import MyModel >>> MyModel.Meta Traceback (последний вызов был последним): файл "<console>", строка 1, в <module> AttributeError: Тип объекта «MyModel» не имеет атрибута «мета»
  • 0
    Вам нужно подчеркнуть, например, MyUser.objects.get(pk=1)._meta
Показать ещё 6 комментариев
19

Класс Django Model специально обрабатывает атрибут с именем Meta, который является классом. Это не общая вещь Питона.

Метатеки Python совершенно разные.

  • 12
    Я думаю, что ваш ответ недостаточно ясен - не могли бы вы рассказать, как работает Meta класс? Я полагаю, что ОП спросила конкретно об этом.
0

Ответы, которые утверждают, что модель 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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню