Модель _meta API
-
class Options[source]
API модели _meta лежит в основе Django ORM. Она позволяет другим частям системы, таким как поиск, запросы, формы и админка, понимать возможности каждой модели. К API можно получить доступ через атрибут _meta каждого класса модели, который является экземпляром объекта django.db.models.options.Options.
Предоставляемые методы могут использоваться для:
- Получения всех экземпляров полей модели
- Получения одного экземпляра поля модели по имени
API модели _meta всегда существовал как внутренняя часть Django, но не был официально документирован и поддерживался. В рамках усилий по публикации этого API некоторые уже существующие точки входа в API немного изменились. Предоставлено руководство по миграции, чтобы помочь в конвертации вашего кода на использование нового, официального API.
API доступа к полям
Получение одного экземпляра поля модели по имени
-
Options.get_field(field_name)[source] -
Возвращает экземпляр поля по заданному имени поля.
Имя поля
field_nameможет быть именем поля в модели, полем в абстрактной или унаследованной модели, или полем, определённым в другой модели, которая указывает на модель. В последнем случае,field_nameбудет именем, заданным пользователем, или автоматически сгенерированным Django.Hidden fieldsне может быть получено по имени.Если поле с заданным именем не найдено, будет поднято исключение
FieldDoesNotExist.>>> from django.contrib.auth.models import User # A field on the model >>> User._meta.get_field('username') <django.db.models.fields.CharField: username> # A field from another model that has a relation with the current model >>> User._meta.get_field('logentry') <ManyToOneRel: admin.logentry> # A non existent field >>> User._meta.get_field('does_not_exist') Traceback (most recent call last): ... FieldDoesNotExist: User has no field named 'does_not_exist'Устарело начиная с версии 1.8:
Options.get_field()ранее принимал параметрmany_to_manyкоторый мог быть установлен вFalseдля избежания поискаManyToManyField. Старое поведение сохранено для обратной совместимости, однако параметр и это поведение устарели.Если вы хотите отфильтровать
ManyToManyField, вы можете проверить атрибутField.many_to_manyпосле вызоваget_field().
Получение всех экземпляров полей модели
-
Options.get_fields(include_parents=True, include_hidden=False)[source] -
Возвращает кортеж полей, связанных с моделью.
get_fields()принимает два параметра, которые можно использовать для управления возвращаемыми полями:-
include_parents -
Trueпо умолчанию. Рекурсивно включает поля, определенные в родительских классах. Если установлено вFalse,get_fields()будет искать только поля, объявленные непосредственно в текущей модели. Поля из моделей, которые непосредственно наследуются от абстрактных моделей или прокси-классов, считаются локальными, а не родительскими. -
include_hidden -
Falseпо умолчанию. Если установлено вTrue,get_fields()будет включать поля, которые используются для поддержки функциональности других полей. Это также будет включать любые поля, имеющиеrelated_name(такие какManyToManyFieldилиForeignKey), начинающиеся с «+».
>>> from django.contrib.auth.models import User >>> User._meta.get_fields() (<ManyToOneRel: admin.logentry>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: password>, <django.db.models.fields.DateTimeField: last_login>, <django.db.models.fields.BooleanField: is_superuser>, <django.db.models.fields.CharField: username>, <django.db.models.fields.CharField: first_name>, <django.db.models.fields.CharField: last_name>, <django.db.models.fields.EmailField: email>, <django.db.models.fields.BooleanField: is_staff>, <django.db.models.fields.BooleanField: is_active>, <django.db.models.fields.DateTimeField: date_joined>, <django.db.models.fields.related.ManyToManyField: groups>, <django.db.models.fields.related.ManyToManyField: user_permissions>) # Also include hidden fields. >>> User._meta.get_fields(include_hidden=True) (<ManyToOneRel: auth.user_groups>, <ManyToOneRel: auth.user_user_permissions>, <ManyToOneRel: admin.logentry>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.CharField: password>, <django.db.models.fields.DateTimeField: last_login>, <django.db.models.fields.BooleanField: is_superuser>, <django.db.models.fields.CharField: username>, <django.db.models.fields.CharField: first_name>, <django.db.models.fields.CharField: last_name>, <django.db.models.fields.EmailField: email>, <django.db.models.fields.BooleanField: is_staff>, <django.db.models.fields.BooleanField: is_active>, <django.db.models.fields.DateTimeField: date_joined>, <django.db.models.fields.related.ManyToManyField: groups>, <django.db.models.fields.related.ManyToManyField: user_permissions>)
-
Миграция с устаревшего API
В рамках формализации API Model._meta (из класса django.db.models.options.Options), ряд методов и свойств устарел и будет удален в Django 1.10.
Эти старые API можно воспроизвести, либо:
- вызвав
Options.get_field(), или; - вызвав
Options.get_fields()для получения списка всех полей, а затем отфильтровав этот список с помощью атрибутов полей, которые описывают (или извлекают в случае с вариантами_with_model) свойства нужных полей.
Хотя возможно создать строго эквивалентные замены старых методов, это может быть не лучшим подходом. Выделение времени на рефакторинг любых циклов по полям для лучшего использования нового API — и возможно включение полей, которые ранее были исключены — почти наверняка приведет к улучшению кода.
Предполагая, что у вас есть модель с именем MyModel, следующие замены можно внести, чтобы преобразовать ваш код в новый API:
-
MyModel._meta.get_field(name)становится:f = MyModel._meta.get_field(name)
затем проверьте, если:
-
f.auto_created == False, так как новый APIget_field()найдёт «обратные» отношения, и: -
f.is_relation and f.related_model is None, так как новый APIget_field()найдётGenericForeignKeyотношения.
-
-
MyModel._meta.get_field_by_name(name)возвращает кортеж из этих четырех значений с последующими заменями:-
fieldможет быть найдено с помощьюMyModel._meta.get_field(name) -
modelможет быть найдено через атрибутmodelполя. -
directможет быть найдено с помощью:not field.auto_created or field.concreteПроверка
auto_createdисключает все «прямые» и «обратные» отношения, которые создаются Django, но также включаетAutoFieldиOneToOneFieldв прокси-моделях. Мы избегаем фильтрации этих атрибутов с помощью атрибутаconcrete. -
m2mможет быть найдено через атрибутmany_to_manyполя.
-
-
MyModel._meta.get_fields_with_model()становится:[ (f, f.model if f.model != MyModel else None) for f in MyModel._meta.get_fields() if not f.is_relation or f.one_to_one or (f.many_to_one and f.related_model) ] -
MyModel._meta.get_concrete_fields_with_model()становится:[ (f, f.model if f.model != MyModel else None) for f in MyModel._meta.get_fields() if f.concrete and ( not f.is_relation or f.one_to_one or (f.many_to_one and f.related_model) ) ] -
MyModel._meta.get_m2m_with_model()становится:[ (f, f.model if f.model != MyModel else None) for f in MyModel._meta.get_fields() if f.many_to_many and not f.auto_created ] -
MyModel._meta.get_all_related_objects()становится:[ f for f in MyModel._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created and not f.concrete ] -
MyModel._meta.get_all_related_objects_with_model()становится:[ (f, f.model if f.model != MyModel else None) for f in MyModel._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created and not f.concrete ] -
MyModel._meta.get_all_related_many_to_many_objects()становится:[ f for f in MyModel._meta.get_fields(include_hidden=True) if f.many_to_many and f.auto_created ] -
MyModel._meta.get_all_related_m2m_objects_with_model()становится:[ (f, f.model if f.model != MyModel else None) for f in MyModel._meta.get_fields(include_hidden=True) if f.many_to_many and f.auto_created ] -
MyModel._meta.get_all_field_names()становится:from itertools import chain list(set(chain.from_iterable( (field.name, field.attname) if hasattr(field, 'attname') else (field.name,) for field in MyModel._meta.get_fields() # For complete backwards compatibility, you may want to exclude # GenericForeignKey from the results. if not (field.many_to_one and field.related_model is None) )))Это обеспечивает 100% обратную совместимость, гарантируя, что включены как имена полей, так и имена атрибутов
ForeignKeys, но поля, связанные сGenericForeignKeys, исключаются. Более простой вариант будет:[f.name for f in MyModel._meta.get_fields()]
Хотя это не 100% обратная совместимость, это может быть достаточно в многих ситуациях.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.9/ref/models/meta/