Spec-Zone.ru › Django 1.9

Модель _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, так как новый API get_field() найдёт «обратные» отношения, и:
    • f.is_relation and f.related_model is None, так как новый API get_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/

Spec-Zone.ru

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