Представления
Написание базовых представлений
Если ваш плагин будет предоставлять собственную страницу или страницы в веб-интерфейсе InfraVision, вам нужно будет определить представления. Представление — это часть бизнес-логики, которая выполняет действие и/или отрисовывает страницу при выполнении запроса к определённому URL. HTML-контент отрисовывается с использованием шаблона. Представления обычно определяются в views.py, а шаблоны URL — в urls.py.
В качестве примера давайте напишем представление, которое отображает случайное животное и звук, который оно издаёт. Мы используем общий класс View Django, чтобы минимизировать количество шаблонного кода.
from django.shortcuts import render
from django.views.generic import View
from .models import Animal
class RandomAnimalView(View):
"""
Отображение случайно выбранного животного.
"""
def get(self, request):
animal = Animal.objects.order_by('?').first()
return render(request, 'netbox_animal_sounds/animal.html', {
'animal': animal,
})
Это представление получает случайный экземпляр Animal из базы данных и передаёт его как контекстную переменную при отрисовке шаблона с именем animal.html. HTTP GET запросы обрабатываются методом get() представления, а POST запросы обрабатываются его методом post().
Наш пример выше чрезвычайно прост, но представления могут делать практически всё что угодно. Обычно именно в них будет находиться основная функциональность вашего плагина. Представления также не ограничены возвратом HTML-контента: представление может возвращать CSV-файл или изображение, например. Для получения дополнительной информации о представлениях см. документацию Django.
Регистрация URL
Чтобы сделать представление доступным для пользователей, нам нужно зарегистрировать для него URL. Мы делаем это в urls.py, определяя переменную urlpatterns, содержащую список путей.
from django.urls import path
from . import views
urlpatterns = [
path('random/', views.RandomAnimalView.as_view(), name='random_animal'),
]
Шаблон URL имеет три компонента:
route— уникальная часть URL, выделенная для этого представленияview— само представлениеname— короткое имя, используемое для внутренней идентификации пути URL
Это делает наше представление доступным по URL /plugins/animal-sounds/random/. (Помните, наш класс AnimalSoundsConfig устанавливает базовый URL нашего плагина как animal-sounds.) Просмотр этого URL должен показать базовый шаблон InfraVision с нашим пользовательским контентом внутри.
Представления моделей InfraVision
InfraVision предоставляет несколько общих классов представлений и дополнительные вспомогательные функции для упрощения реализации логики плагина. Рекомендуется использовать их всегда, когда это возможно, чтобы снизить накладные расходы на поддержку плагинов.
Классы представлений
Общие классы представлений (документированные ниже) облегчают общие операции, такие как создание, просмотр, изменение и удаление объектов. Плагины могут наследоваться от этих представлений для собственного использования.
| Класс представления | Описание |
|---|---|
ObjectView |
Просмотр одного объекта |
ObjectEditView |
Создание или редактирование одного объекта |
ObjectDeleteView |
Удаление одного объекта |
ObjectChildrenView |
Список дочерних объектов в контексте родителя |
ObjectListView |
Просмотр списка объектов |
BulkImportView |
Импорт набора новых объектов |
BulkEditView |
Редактирование нескольких объектов |
BulkRenameView |
Переименование нескольких объектов |
BulkDeleteView |
Удаление нескольких объектов |
Внимание
Обратите внимание, что в настоящее время поддерживаются только классы, которые появляются в этой документации. Хотя другие классы могут присутствовать в модуле views.generic, они пока не поддерживаются для использования плагинами.
Регистрация URL
Процесс регистрации URL в InfraVision состоит из двух частей:
- Классы представлений могут быть декорированы с помощью
@register_model_view(). Это регистрирует новый URL для модели. - Все URL модели могут быть включены в
urls.pyс помощью функцииget_model_urls(). Этот вызов обычно требуется дважды: один раз для импорта общих представлений модели и ещё раз для импорта детальных представлений модели, привязанных к первичному ключу объекта.
::: utilities.views.register_model_view
Изменено в InfraVision v4.2
В InfraVision v4.2 функция register_model_view() была расширена для поддержки регистрации представлений списков путём передачи detail=False.
::: utilities.urls.get_model_urls
Изменено в InfraVision v4.2
В InfraVision v4.2 функция get_model_urls() была расширена для поддержки получения зарегистрированных общих представлений модели (например, для списка объектов) путём передачи detail=False.
Пример использования
# views.py
from netbox.views.generic import ObjectEditView
from utilities.views import register_model_view
from .models import Thing
@register_model_view(Thing, name='add', detail=False)
@register_model_view(Thing, name='edit')
class ThingEditView(ObjectEditView):
queryset = Thing.objects.all()
template_name = 'myplugin/thing.html'
...
# urls.py
from django.urls import include, path
from utilities.urls import get_model_urls
urlpatterns = [
path('thing/', include(get_model_urls('myplugin', 'thing', detail=False))),
path('thing/<int:pk>/', include(get_model_urls('myplugin', 'thing'))),
...
]
Представления объектов
Ниже приведены определения классов для представлений объектов InfraVision. Эти представления обрабатывают CRUD-операции для отдельных объектов. Представления просмотра, добавления/редактирования и удаления наследуются от BaseObjectView, который не предназначен для прямого использования.
::: netbox.views.generic.base.BaseObjectView options: members: - get_queryset - get_object - get_extra_context
::: netbox.views.generic.ObjectView options: members: - get_template_name
::: netbox.views.generic.ObjectEditView options: members: - alter_object
::: netbox.views.generic.ObjectDeleteView options: members: false
::: netbox.views.generic.ObjectChildrenView options: members: - get_children - prep_table_data
Представления множества объектов
Ниже приведены определения классов для представлений множества объектов InfraVision. Эти представления обрабатывают одновременные действия для наборов объектов. Представления списка, импорта, редактирования и удаления наследуются от BaseMultiObjectView, который не предназначен для прямого использования.
::: netbox.views.generic.base.BaseMultiObjectView options: members: - get_queryset - get_extra_context
::: netbox.views.generic.ObjectListView options: members: - get_table - export_table - export_template
::: netbox.views.generic.BulkImportView options: members: - save_object
::: netbox.views.generic.BulkEditView options: members: false
::: netbox.views.generic.BulkRenameView options: members: false
::: netbox.views.generic.BulkDeleteView options: members: - get_form
Представления функций
Эти представления предоставляются для включения или улучшения определённых функций моделей InfraVision, таких как журналирование изменений или ведение журнала записей. Обычно их не нужно наследовать: их можно использовать напрямую, например, в пути URL.
Примечание
Эти представления функций автоматически регистрируются для всех моделей, реализующих соответствующую функцию. Обычно нет необходимости их переопределять. Однако, если это всё же требуется, URL должен быть зарегистрирован вручную в urls.py вместо использования функции или декоратора register_model_view().
::: netbox.views.generic.ObjectChangeLogView options: members: - get_form
::: netbox.views.generic.ObjectJournalView options: members: - get_form
Расширение базовых представлений
Дополнительные вкладки
Плагины могут "прикреплять" пользовательское представление к модели InfraVision, регистрируя его с помощью register_model_view(). Чтобы включить вкладку для этого представления в интерфейсе InfraVision, объявите экземпляр TabView с именем tab и добавьте его в словарь контекста шаблона:
from dcim.models import Site
from myplugin.models import Stuff
from netbox.views import generic
from utilities.views import ViewTab, register_model_view
@register_model_view(Site, name='myview', path='some-other-stuff')
class MyView(generic.ObjectView):
...
tab = ViewTab(
label='Other Stuff',
badge=lambda obj: Stuff.objects.filter(site=obj).count(),
permission='myplugin.view_stuff'
)
def get(self, request, pk):
...
return render(
request,
"myplugin/mytabview.html",
context={
"tab": self.tab,
},
)
::: utilities.views.ViewTab
Дополнительный контент шаблонов
Плагины могут внедрять пользовательский контент в определённые области базовых представлений InfraVision. Это достигается путём создания подкласса PluginTemplateExtension, опционального указания одной или нескольких конкретных моделей InfraVision и определения желаемых методов для отрисовки пользовательского контента. Доступны пять методов:
| Метод | Представление | Описание |
|---|---|---|
head() |
Все | Пользовательские включения блока HTML <head> |
navbar() |
Все | Внедрение контента внутрь верхней панели навигации |
list_buttons() |
Список | Добавление кнопок вверху страницы |
buttons() |
Просмотр объекта | Добавление кнопок вверху страницы |
alerts() |
Просмотр объекта | Внедрение контента вверху страницы |
left_page() |
Просмотр объекта | Внедрение контента в левую часть страницы |
right_page() |
Просмотр объекта | Внедрение контента в правую часть страницы |
full_width_page() |
Просмотр объекта | Внедрение контента по всей ширине внизу страницы |
Кроме того, для удобства доступен метод render(). Этот метод принимает имя шаблона для отрисовки и любые дополнительные контекстные данные, которые вы хотите передать. Его использование опционально.
Чтобы контролировать, куда внедряется пользовательский контент, авторы плагинов могут указать итерируемый объект моделей, переопределив атрибут models в подклассе. Расширения, которые не указывают набор моделей, будут вызываться в каждом представлении, где это поддерживается.
Когда создаётся экземпляр PluginTemplateExtension, контекстные данные присваиваются self.context. Доступные данные включают:
object— просматриваемый объект (только для представлений объекта)model— модель представления списка (только для представлений списка)request— текущий запросsettings— глобальные настройки InfraVisionconfig— параметры конфигурации, специфичные для плагина
Например, доступ к {{ request.user }} в шаблоне вернёт текущего пользователя.
Объявленные подклассы должны быть собраны в список или кортеж для интеграции с InfraVision. По умолчанию InfraVision ищет итерируемый объект с именем template_extensions в файле template_content.py. (Это можно переопределить, установив template_extensions в пользовательское значение в PluginConfig плагина.) Пример приведён ниже.
from netbox.plugins import PluginTemplateExtension
from .models import Animal
class SiteAnimalCount(PluginTemplateExtension):
models = ['dcim.site']
def right_page(self):
return self.render('netbox_animal_sounds/inc/animal_count.html', extra_context={
'animal_count': Animal.objects.count(),
})
template_extensions = [SiteAnimalCount]