You're probably familiar with object lists in NetBox. This is how we display all the instances of a certain type of object, such as sites or devices, in the user interface. These lists are generated by table classes defined for each model, utilizing the django-tables2 library.
While it would be feasible to generate raw HTML for <table>
elements directly within the template, this would be cumbersome and difficult to maintain. Additionally, these dynamic table classes provide convenient functionality like sorting and pagination.
🟦 Note: If you skipped the previous step, run git checkout step02-models
.
We'll create two tables, one for each of our models. Begin by creating tables.py
in the netbox_access_lists/
directory.
$ cd netbox_access_lists/
$ edit tables.py
At the top of this file, import the django-tables2
library. This will provide the column classes for fields we wish to customize. We'll also import NetBox's NetBoxTable
class, which will serve as the base class for our tables, and ChoiceFieldColumn
. Finally we import our plugin's models from models.py
.
import django_tables2 as tables
from netbox.tables import NetBoxTable, ChoiceFieldColumn
from .models import AccessList, AccessListRule
Create a class named AccessListTable
as a subclass of NetBoxTable
. Within this class, create a child Meta
class inheriting from NetBoxTable.Meta
; this will define the table's model, fields, and default columns.
class AccessListTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = AccessList
fields = ('pk', 'id', 'name', 'default_action', 'comments', 'actions')
default_columns = ('name', 'default_action')
The model
attribute tells django-tables2
which model to use when building the table, and the fields
attribute dictates which model fields get added to the table. default_columns
controls which of the available columns are displayed by default.
The pk
and actions
columns render the checkbox selectors and dropdown menus, respectively, for each table row; these are provided by the NetBoxTable class. The id
column will display the object's numeric primary key, which is included on almost every table in NetBox but generally disabled by default. The other three columns derive from the fields we defined on the AccessList
model.
What we have so far is sufficient to render a table, but we can make some small improvements. First, let's make the name
column a link to each object. To do this, we'll override the default column by defining name
on the class and passing linkify=True
.
class AccessListTable(NetBoxTable):
name = tables.Column(
linkify=True
)
Also, recall that the default_action
field on the AccessList
model is a choice field, with a color assigned to each choice. To display these values, we'll use NetBox's ChoiceFieldColumn
class.
default_action = ChoiceFieldColumn()
It would also be nice to include a count showing the number of rules each access list has assigned to it. We can add a custom column named rule_count
to show this. (The data for this column will be annotated by the view; more on this in step five.) We'll also need to add this column to our fields
and (optionally) default_columns
under the Meta
subclass. Our finished table should look like this:
class AccessListTable(NetBoxTable):
name = tables.Column(
linkify=True
)
default_action = ChoiceFieldColumn()
rule_count = tables.Column()
class Meta(NetBoxTable.Meta):
model = AccessList
fields = ('pk', 'id', 'name', 'rule_count', 'default_action', 'comments', 'actions')
default_columns = ('name', 'rule_count', 'default_action')
We'll also create a table for our AccessListRule
model using the same approach as above. Start by linkifying the access_list
and index
columns. The former will link to the parent access list, and the latter will link to the individual rule. We also want to declare protocol
and action
as ChoiceFieldColumn
instances.
class AccessListRuleTable(NetBoxTable):
access_list = tables.Column(
linkify=True
)
index = tables.Column(
linkify=True
)
protocol = ChoiceFieldColumn()
action = ChoiceFieldColumn()
class Meta(NetBoxTable.Meta):
model = AccessListRule
fields = (
'pk', 'id', 'access_list', 'index', 'source_prefix', 'source_ports', 'destination_prefix',
'destination_ports', 'protocol', 'action', 'description', 'actions',
)
default_columns = (
'access_list', 'index', 'source_prefix', 'source_ports', 'destination_prefix',
'destination_ports', 'protocol', 'action', 'actions',
)
This should be all we need to list these objects in the UI. Next, we'll define some forms to enable creating and modifying objects.
⬅️ Step 2: Models | Step 4: Forms ➡️