数据库模型
创建模型
如果您的插件在NetBox中引入了新类型的对象,您可能希望为其创建一个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(没有下划线)。在模型名称中使用下划线将导致权限问题。
启用NetBox功能
插件模型可以通过继承NetBox的NetBoxModel
类来利用某些NetBox功能。此类扩展了插件模型以启用NetBox独有的功能,包括:
- 书签
- 更改日志
- 克隆
- 自定义字段
- 自定义链接
- 自定义验证
- 导出模板
- 记录日志
- 标签
- Webhooks
此类执行两个关键功能:
- 应用于这些功能的操作所需的任何字段、方法和/或属性
- 注册模型,表示该模型使用了这些功能
只需在定义插件中的模型时将其子类化为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
。这将从通用对象类型列表中省略它。
单独启用功能
如果您更喜欢仅为插件模型启用这些功能的子集,NetBox为每个功能提供了单独的“混合”类。在定义模型时,可以单独为每个功能子类化它们。(您的模型还需要继承自Django内置的Model
类。)
例如,如果我们只想支持标签和导出模板,我们可以从NetBox的ExportTemplatesMixin
和TagsMixin
类中继承,并从Django的Model
类中继承(继承所有可用的混合类基本上与子类化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
管理命令自动创建迁移。(确保首先安装和启用了您的插件,否则找不到它。)
注意
NetBox在makemigrations
命令周围执行了一项保护措施,以防止普通用户意外创建错误的模式迁移。为了在插件开发中启用此命令,请在configuration.py
中设置DEVELOPER=True
。
$ ./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”模块中可能存在其他类,但它们尚不支持供插件使用。
BookmarksMixin (Model)
django-model
Enables support for user bookmarks.
bookmarks: GenericRelation
blank
django-field
nullable
bookmarks
ChangeLoggingMixin (Model)
django-model
Provides change logging support for a model. Adds the created
and last_updated
fields.
created: DateTimeField
blank
django-field
nullable
created
last_updated: DateTimeField
blank
django-field
nullable
last updated
serialize_object(self, exclude=None)
Return a JSON representation of the instance. Models can override this method to replace or extend the default
serialization logic provided by the serialize_object()
utility function.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
exclude |
An iterable of attribute names to omit from the serialized output |
None |
snapshot(self)
Save a snapshot of the object's current state in preparation for modification. The snapshot is saved as
_prechange_snapshot
on the instance.
to_objectchange(self, action)
Return a new ObjectChange representing a change made to this object. This will typically be called automatically by ChangeLoggingMiddleware.
CloningMixin (Model)
django-model
Provides the clone() method used to prepare a copy of existing objects.
clone(self)
Returns a dictionary of attributes suitable for creating a copy of the current instance. This is used for pre-
populating an object creation form in the UI. By default, this method will replicate any fields listed in the
model's clone_fields
list (if defined), but it can be overridden to apply custom logic.
class MyModel(NetBoxModel):
def clone(self):
attrs = super().clone()
attrs['extra-value'] = 123
return attrs
CustomLinksMixin (Model)
django-model
Enables support for custom links.
CustomFieldsMixin (Model)
django-model
Enables support for custom fields.
custom_field_data: JSONField
blank
django-field
custom field data
cf
cached
property
writable
Return a dictionary mapping each custom field for this instance to its deserialized value.
>>> tenant = Tenant.objects.first()
>>> tenant.cf
{'primary_site': <Site: DM-NYC>, 'cust_id': 'DMI01', 'is_active': True}
custom_fields
cached
property
writable
Return the QuerySet of CustomFields assigned to this model.
>>> tenant = Tenant.objects.first()
>>> tenant.custom_fields
<RestrictedQuerySet [<CustomField: Primary site>, <CustomField: Customer ID>, <CustomField: Is active>]>
get_custom_fields(self, omit_hidden=False)
Return a dictionary of custom fields for a single object in the form {field: value}
.
>>> tenant = Tenant.objects.first()
>>> tenant.get_custom_fields()
{<CustomField: Customer ID>: 'CYB01'}
Parameters:
Name | Type | Description | Default |
---|---|---|---|
omit_hidden |
If True, custom fields with no UI visibility will be omitted. |
False |
get_custom_fields_by_group(self)
Return a dictionary of custom field/value mappings organized by group. Hidden fields are omitted.
>>> tenant = Tenant.objects.first()
>>> tenant.get_custom_fields_by_group()
{
'': {<CustomField: Primary site>: <Site: DM-NYC>},
'Billing': {<CustomField: Customer ID>: 'DMI01', <CustomField: Is active>: True}
}
populate_custom_field_defaults(self)
Apply the default value for each custom field
clean(self)
Hook for doing any extra model-wide validation after clean() has been called on every field by self.clean_fields. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field defined by NON_FIELD_ERRORS.
CustomValidationMixin (Model)
django-model
Enables user-configured validation rules for models.
clean(self)
Hook for doing any extra model-wide validation after clean() has been called on every field by self.clean_fields. Any ValidationError raised by this method will not be associated with a particular field; it will have a special-case association with the field defined by NON_FIELD_ERRORS.
EventRulesMixin (Model)
django-model
Enables support for event rules, which can be used to transmit webhooks or execute scripts automatically.
注意
EventRulesMixin
在NetBox v3.7中从WebhooksMixin
中更名而来。
ExportTemplatesMixin (Model)
django-model
Enables support for export templates.
JournalingMixin (Model)
django-model
Enables support for object journaling. Adds a generic relation (journal_entries
)
to NetBox's JournalEntry model.
journal_entries: GenericRelation
blank
django-field
nullable
journal entries
TagsMixin (Model)
django-model
Enables support for tag assignment. Assigned tags can be managed via the tags
attribute,
which is a TaggableManager
instance.
tags: TaggableManager
django-field
nullable
Tags: A comma-separated list of tags.
选择集
对于支持从预定义选择列表中选择一个或多个值的模型字段,NetBox提供了ChoiceSet
实用类。这可以用来替代常规的选择元组,以提供增强功能,即动态配置和着色。(有关受支持的模型字段的choices
参数,请参阅Django文档。)
要为模型字段定义选择项,请子类化ChoiceSet
并定义一个名为CHOICES
的元组,其中每个成员都是一个两个或三个元组。这些元素是:
- 数据库值
- 相应的用户友好标签
- 分配的颜色(可选)
下面提供了一个完整示例。
注意
作者可能会发现有用的是将每个数据库值声明为类上的常量,并在CHOICES
成员内引用它们。这种约定允许从类外部引用这些值,但不是强制性的。
动态配置
NetBox中的某些模型字段选择可以由管理员配置。例如,Site模型的status
字段的默认值可以被替换或补充为自定义选择。要为ChoiceSet子类启用动态配置,请将其key
定义为字符串,指定其适用的模型和字段名称。例如:
from utilities.choices import ChoiceSet
class StatusChoices(ChoiceSet):
key = 'MyModel.status'
要扩展或替换此选择集的默认值,NetBox管理员可以在FIELD_CHOICES
配置参数下引用它。例如,my_plugin
中的MyModel
上的status
字段将被引用为:
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
)