Spec-Zone.ru › Django 1.11

Модель _meta API

class Options [source]

Модель _meta API является основой Django ORM. Она позволяет другим частям системы, таким как поиск, запросы, формы и админ-панель, понимать возможности каждой модели. К API можно получить доступ через атрибут _meta каждого класса модели, который является экземпляром объекта django.db.models.options.Options.

Предоставляемые методы могут быть использованы для:

  • Получения всех экземпляров полей модели
  • Получения одного экземпляра поля модели по имени

API доступа к полям

Получение одного экземпляра поля модели по имени

Options.get_field(field_name) [source]

Возвращает экземпляр поля, заданного именем поля.

field_name может быть именем поля в модели, полем в абстрактной или унаследованной модели, или полем, определённым в другой модели, которая указывает на эту модель. В последнем случае, field_name будет related_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'

Получение всех экземпляров полей модели

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

В рамках формализации Model._meta API (из класса 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, потому что новый get_field() API найдет «обратные» отношения, и:
    • f.is_relation and f.related_model is None, потому что новый get_field() API найдет 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.11/ref/models/meta/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API