1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Minor tweaks to plugins development doc

This commit is contained in:
Jeremy Stretch
2020-04-10 10:10:27 -04:00
parent d5dbd5ccf1
commit db70f04447
2 changed files with 44 additions and 39 deletions

View File

@ -53,10 +53,9 @@ from setuptools import find_packages, setup
setup( setup(
name='netbox-animal-sounds', name='netbox-animal-sounds',
version='0.1', version='0.1',
description='Show animals and the sounds they make', description='An example NetBox plugin',
url='https://github.com/example-org/animal-sounds', url='https://github.com/netbox-community/netbox-animal-sounds',
author='Author Name', author='Jeremy Stretch',
author_email='author@example.com',
license='Apache 2.0', license='Apache 2.0',
install_requires=[], install_requires=[],
packages=find_packages(), packages=find_packages(),
@ -75,10 +74,11 @@ from extras.plugins import PluginConfig
class AnimalSoundsConfig(PluginConfig): class AnimalSoundsConfig(PluginConfig):
name = 'netbox_animal_sounds' name = 'netbox_animal_sounds'
verbose_name = 'Animal Sounds Plugin' verbose_name = 'Animal Sounds'
description = 'An example plugin for development purposes'
version = '0.1' version = '0.1'
author = 'Author Name' author = 'Jeremy Stretch'
description = 'Show animals and the sounds they make' author_email = 'author@example.com'
base_url = 'animal-sounds' base_url = 'animal-sounds'
required_settings = [] required_settings = []
default_settings = { default_settings = {
@ -161,14 +161,13 @@ For more background on schema migrations, see the [Django documentation](https:/
### Using the Django Admin Interface ### Using the Django Admin Interface
Plugins can optionally expose their models via Django's built-in [administrative interface](https://docs.djangoproject.com/en/stable/ref/contrib/admin/). This can greatly improve troubleshooting ability, particularly during development. To expose a model, simply register it with Netbox's `admin_site` object. An example `admin.py` file for the above model is shown below: Plugins can optionally expose their models via Django's built-in [administrative interface](https://docs.djangoproject.com/en/stable/ref/contrib/admin/). This can greatly improve troubleshooting ability, particularly during development. To expose a model, simply register it using Django's `admin.register()` function. An example `admin.py` file for the above model is shown below:
```python ```python
from django.contrib import admin from django.contrib import admin
from netbox.admin import admin_site
from .models import Animal from .models import Animal
@admin.register(Animal, site=admin_site) @admin.register(Animal)
class AnimalAdmin(admin.ModelAdmin): class AnimalAdmin(admin.ModelAdmin):
list_display = ('name', 'sound') list_display = ('name', 'sound')
``` ```
@ -186,29 +185,39 @@ from django.shortcuts import render
from django.views.generic import View from django.views.generic import View
from .models import Animal from .models import Animal
class RandomAnimalSoundView(View): class RandomAnimalView(View):
"""
Display a randomly-selected animal.
"""
def get(self, request): def get(self, request):
# Retrieve a random animal
animal = Animal.objects.order_by('?').first() animal = Animal.objects.order_by('?').first()
return render(request, 'netbox_animal_sounds/animal.html', {
return render(request, 'netbox_animal_sounds/animal_sound.html', {
'animal': animal, 'animal': animal,
}) })
``` ```
This view retrieves a random animal from the database and and passes it as a context variable when rendering a template named `animal_sound.html`, which doesn't exist yet. To create this template, first create a directory named `templates/netbox_animal_sounds/` within the plugin source directory. (We use the plugin's name as a subdirectory to guard against naming collisions with other plugins.) Then, create `animal_sound.html`: This view retrieves a random animal from the database and and passes it as a context variable when rendering a template named `animal.html`, which doesn't exist yet. To create this template, first create a directory named `templates/netbox_animal_sounds/` within the plugin source directory. (We use the plugin's name as a subdirectory to guard against naming collisions with other plugins.) Then, create `animal.html`:
```jinja2 ```jinja2
{% extends '_base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
{% if animal %} {% with config=settings.PLUGINS_CONFIG.netbox_animal_sounds %}
The {{ animal.name }} says {{ animal.sound }} <h2 class="text-center" style="margin-top: 200px">
{% else %} {% if animal %}
No animals have been created yet! The {{ animal.name|lower }} says
{% endif %} {% if config.loud %}
{{ animal.sound|upper }}!
{% else %}
{{ animal.sound }}
{% endif %}
{% else %}
No animals have been created yet!
{% endif %}
</h2>
{% endwith %}
{% endblock %} {% endblock %}
``` ```
The first line of the template instructs Django to extend the NetBox base template and inject our custom content within its `content` block. The first line of the template instructs Django to extend the NetBox base template and inject our custom content within its `content` block.
@ -220,10 +229,10 @@ Finally, to make the view accessible to users, we need to register a URL for it.
```python ```python
from django.urls import path from django.urls import path
from .views import RandomAnimalSoundView from . import views
urlpatterns = [ urlpatterns = [
path('random-sound/', RandomAnimalSoundView.as_view(), name='random_sound') path('random/', views.RandomAnimalView.as_view(), name='random_animal'),
] ]
``` ```
@ -233,7 +242,7 @@ A URL pattern has three components:
* `view` - The view itself * `view` - The view itself
* `name` - A short name used to identify the URL path internally * `name` - A short name used to identify the URL path internally
This makes our view accessible at the URL `/plugins/animal-sounds/random-sound/`. (Remember, our `AnimalSoundsConfig` class sets our plugin's base URL to `animal-sounds`.) Viewing this URL should show the base NetBox template with our custom content inside it. This makes our view accessible at the URL `/plugins/animal-sounds/random/`. (Remember, our `AnimalSoundsConfig` class sets our plugin's base URL to `animal-sounds`.) Viewing this URL should show the base NetBox template with our custom content inside it.
## REST API Endpoints ## REST API Endpoints
@ -252,7 +261,7 @@ class AnimalSerializer(ModelSerializer):
fields = ('id', 'name', 'sound') fields = ('id', 'name', 'sound')
``` ```
Next, we'll create a generic API viewset that allows basic CRUD (create, read, update, and delete) operations for Animal instances. This is defined in `api/views.py`: Next, we'll create a generic API view set that allows basic CRUD (create, read, update, and delete) operations for Animal instances. This is defined in `api/views.py`:
```python ```python
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
@ -279,7 +288,7 @@ With these three components in place, we can request `/api/plugins/animal-sounds
![NetBox REST API plugin endpoint](../media/plugins/plugin_rest_api_endpoint.png) ![NetBox REST API plugin endpoint](../media/plugins/plugin_rest_api_endpoint.png)
!!! note !!! warning
This example is provided as a minimal reference implementation only. It does not address authentication, performance, or myriad other concerns that plugin authors should have. This example is provided as a minimal reference implementation only. It does not address authentication, performance, or myriad other concerns that plugin authors should have.
## Navigation Menu Items ## Navigation Menu Items
@ -292,7 +301,7 @@ from utilities.choices import ButtonColorChoices
menu_items = ( menu_items = (
PluginMenuItem( PluginMenuItem(
link='plugins:netbox_animal_sounds:random_sound', link='plugins:netbox_animal_sounds:random_animal',
link_text='Random sound', link_text='Random sound',
buttons=( buttons=(
PluginMenuButton('home', 'Button A', 'fa-info', ButtonColorChoices.BLUE), PluginMenuButton('home', 'Button A', 'fa-info', ButtonColorChoices.BLUE),
@ -341,21 +350,17 @@ Declared subclasses should be gathered into a list or tuple for integration with
```python ```python
from extras.plugins import PluginTemplateExtension from extras.plugins import PluginTemplateExtension
from .models import Animal
class AddSiteAnimal(PluginTemplateExtension): class SiteAnimalCount(PluginTemplateExtension):
model = 'dcim.site' model = 'dcim.site'
def full_width_page(self): def right_page(self):
return self.render('netbox_animal_sounds/site.html') return self.render('netbox_animal_sounds/inc/animal_count.html', extra_context={
'animal_count': Animal.objects.count(),
})
class AddRackAnimal(PluginTemplateExtension): template_extensions = [SiteAnimalCount]
model = 'dcim.rack'
def left_page(self):
extra_data = {'foo': 123}
return self.render('netbox_animal_sounds/rack.html', extra_data)
template_extensions = [AddSiteAnimal, AddRackAnimal]
``` ```
## Caching Configuration ## Caching Configuration