Модели базы данных
Создание моделей
Если ваш плагин вводит новый тип объекта в InfraVision, вам, вероятно, потребуется создать для него модель Django. Модель — это по сути Python-представление таблицы базы данных, с атрибутами, представляющими отдельные столбцы. Экземпляры модели (объекты) могут быть созданы, изменены и удалены с помощью запросов. Модели должны быть определены в файле с именем models.py.
Ниже приведён пример файла models.py, содержащего модель с двумя символьными (текстовыми) полями:
from django.db import models
class MyModel(models.Model):
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=50)
def __str__(self):
return f'{self.foo} {self.bar}'
Каждая модель по умолчанию включает числовой первичный ключ. Это значение генерируется автоматически базой данных и может быть доступно как pk или id.
Примечание
Имена моделей должны соответствовать стандартам PEP8 и быть в формате CapWords (без подчёркиваний). Использование подчёркиваний в именах моделей приведёт к проблемам с разрешениями.
Включение функций InfraVision
Модели плагинов могут использовать определённые функции моделей (такие как теги, пользовательские поля, правила событий и т.д.) путём наследования от класса NetBoxModel InfraVision. Этот класс выполняет две важные функции:
- Применяет все поля, методы и/или атрибуты, необходимые для работы этих функций
- Регистрирует модель в InfraVision как использующую эти функции
Просто наследуйтесь от NetBoxModel при определении модели в вашем плагине:
# models.py
from django.db import models
from netbox.models import NetBoxModel
class MyModel(NetBoxModel):
foo = models.CharField()
...
Свойства NetBoxModel
docs_url
Этот атрибут указывает URL, по которому можно найти документацию для этой модели. По умолчанию он возвращает /static/docs/models/<app_label>/<model_name>/. Модели плагинов могут переопределить это для возврата пользовательского URL. Например, вы можете направить пользователя на документацию вашего плагина, размещённую на ReadTheDocs.
_netbox_private
По умолчанию любая модель, введённая плагином, появится в списке доступных типов объектов, например, при создании пользовательского поля или определённых виджетов панели управления. Если ваша модель предназначена только для "закулисного использования" и не должна показываться конечным пользователям, установите _netbox_private в True. Это исключит её из списка общих типов объектов.
Включение функций по отдельности
Если вы предпочитаете включить только подмножество этих функций для модели плагина, InfraVision предоставляет отдельный класс-примесь для каждой функции. Вы можете наследоваться от каждого из них индивидуально при определении вашей модели. (Ваша модель также должна наследоваться от встроенного класса Model Django.)
Например, если мы хотим поддерживать только теги и шаблоны экспорта, мы бы наследовались от классов ExportTemplatesMixin и TagsMixin InfraVision, и от класса Model Django. (Наследование от всех доступных примесей по сути то же самое, что наследование от NetBoxModel.)
# models.py
from django.db import models
from netbox.models.features import ExportTemplatesMixin, TagsMixin
class MyModel(ExportTemplatesMixin, TagsMixin, models.Model):
foo = models.CharField()
...
Миграции базы данных
После завершения определения модели(ей) для вашего плагина вам нужно будет создать миграции схемы базы данных. Файл миграции — это по сути набор инструкций для манипуляции базой данных PostgreSQL для поддержки вашей новой модели или для изменения существующих моделей. Создание миграций обычно может быть выполнено автоматически с помощью команды управления Django makemigrations. (Убедитесь, что ваш плагин установлен и включён, иначе он не будет найден.)
Включите режим разработчика
InfraVision применяет защиту вокруг команды makemigrations, чтобы защитить обычных пользователей от случайного создания ошибочных миграций схемы. Чтобы включить эту команду для разработки плагина, установите DEVELOPER=True в configuration.py.
$ ./manage.py makemigrations my_plugin
Migrations for 'my_plugin':
/home/jstretch/animal_sounds/my_plugin/migrations/0001_initial.py
- Create model MyModel
Далее мы можем применить миграцию к базе данных с помощью команды migrate:
$ ./manage.py migrate my_plugin
Operations to perform:
Apply all migrations: my_plugin
Running migrations:
Applying my_plugin.0001_initial... OK
Для получения дополнительной информации о миграциях базы данных см. документацию Django.
Справочник по примесям функций
Внимание
Обратите внимание, что в настоящее время поддерживаются только классы, которые появляются в этой документации. Хотя другие классы могут присутствовать в модуле features, они пока не поддерживаются для использования плагинами.
::: netbox.models.features.BookmarksMixin
::: netbox.models.features.ChangeLoggingMixin
::: netbox.models.features.CloningMixin
::: netbox.models.features.ContactsMixin
::: netbox.models.features.CustomLinksMixin
::: netbox.models.features.CustomFieldsMixin
::: netbox.models.features.CustomValidationMixin
::: netbox.models.features.EventRulesMixin
::: netbox.models.features.ExportTemplatesMixin
::: netbox.models.features.JobsMixin
::: netbox.models.features.JournalingMixin
::: netbox.models.features.TagsMixin
Пользовательские функции моделей
В дополнение к использованию функций моделей, предоставляемых нативно InfraVision (перечисленных выше), плагины могут регистрировать свои собственные функции моделей. Это делается с помощью функции register_model_feature() из netbox.utils. Эта функция принимает два аргумента: имя функции и вызываемый объект, который принимает класс модели. Вызываемый объект должен возвращать булево значение, указывающее, поддерживает ли данная модель названную функцию.
Эта функция может использоваться как декоратор:
@register_model_feature('foo')
def supports_foo(model):
# Ваша логика здесь
Или её можно вызвать напрямую:
register_model_feature('foo', supports_foo)
Совет
Рассмотрите выполнение регистрации функций внутри метода ready() вашего PluginConfig.
Наборы вариантов выбора
Для полей модели, которые поддерживают выбор одного или нескольких значений из предопределённого списка вариантов, InfraVision предоставляет служебный класс ChoiceSet. Он может использоваться вместо обычного кортежа вариантов для предоставления расширенной функциональности, а именно динамической конфигурации и раскраски. (См. документацию Django по параметру choices для поддерживаемых полей модели.)
Чтобы определить варианты для поля модели, создайте подкласс ChoiceSet и определите кортеж с именем CHOICES, каждый член которого является кортежем из двух или трёх элементов. Эти элементы:
- Значение в базе данных
- Соответствующая человекочитаемая метка
- Назначенный цвет (опционально)
Полный пример приведён ниже.
Примечание
Авторам может быть полезно объявить каждое из значений базы данных как константы класса и ссылаться на них в членах CHOICES. Это соглашение позволяет ссылаться на значения извне класса, однако это не является строго обязательным.
Динамическая конфигурация
Некоторые варианты полей модели в InfraVision могут быть настроены администратором. Например, значения по умолчанию для поля status модели Site могут быть заменены или дополнены пользовательскими вариантами. Чтобы включить динамическую конфигурацию для подкласса ChoiceSet, определите его key как строку, указывающую имя модели и поля, к которым он применяется. Например:
from utilities.choices import ChoiceSet
class StatusChoices(ChoiceSet):
key = 'MyModel.status'
Чтобы расширить или заменить значения по умолчанию для этого набора вариантов, администратор InfraVision может затем ссылаться на него в параметре конфигурации FIELD_CHOICES. Например, поле status на MyModel в my_plugin будет указываться как:
FIELD_CHOICES = {
'my_plugin.MyModel.status': (
# Пользовательские варианты
)
}
Пример
# choices.py
from utilities.choices import ChoiceSet
class StatusChoices(ChoiceSet):
key = 'MyModel.status'
STATUS_FOO = 'foo'
STATUS_BAR = 'bar'
STATUS_BAZ = 'baz'
CHOICES = [
(STATUS_FOO, 'Foo', 'red'),
(STATUS_BAR, 'Bar', 'green'),
(STATUS_BAZ, 'Baz', 'blue'),
]
Внимание
Для правильной работы динамической конфигурации CHOICES должен быть изменяемым списком, а не кортежем.
# models.py
from django.db import models
from .choices import StatusChoices
class MyModel(models.Model):
status = models.CharField(
max_length=50,
choices=StatusChoices,
default=StatusChoices.STATUS_FOO
)