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

Merge v3.1.6

This commit is contained in:
jeremystretch
2022-01-17 11:12:54 -05:00
parent 7767692394
commit 3e3880823b
33 changed files with 225 additions and 129 deletions

View File

@@ -100,5 +100,5 @@ class CircuitTerminationSerializer(ValidatedModelSerializer, LinkTerminationSeri
fields = [
'id', 'url', 'display', 'circuit', 'term_side', 'site', 'provider_network', 'port_speed', 'upstream_speed',
'xconnect_id', 'pp_info', 'description', 'mark_connected', 'cable', 'link_peer', 'link_peer_type',
'_occupied',
'_occupied', 'created', 'last_updated',
]

View File

@@ -66,7 +66,7 @@ class ProviderTable(BaseTable):
model = Provider
fields = (
'pk', 'id', 'name', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'circuit_count',
'comments', 'tags',
'comments', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'asn', 'account', 'circuit_count')
@@ -90,7 +90,9 @@ class ProviderNetworkTable(BaseTable):
class Meta(BaseTable.Meta):
model = ProviderNetwork
fields = ('pk', 'id', 'name', 'provider', 'service_id', 'description', 'comments', 'tags')
fields = (
'pk', 'id', 'name', 'provider', 'service_id', 'description', 'comments', 'created', 'last_updated', 'tags',
)
default_columns = ('pk', 'name', 'provider', 'service_id', 'description')
@@ -112,7 +114,9 @@ class CircuitTypeTable(BaseTable):
class Meta(BaseTable.Meta):
model = CircuitType
fields = ('pk', 'id', 'name', 'circuit_count', 'description', 'slug', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'circuit_count', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'circuit_count', 'description', 'slug')
@@ -149,7 +153,7 @@ class CircuitTable(BaseTable):
model = Circuit
fields = (
'pk', 'id', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'install_date',
'commit_rate', 'description', 'comments', 'tags',
'commit_rate', 'description', 'comments', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'description',

View File

@@ -221,7 +221,7 @@ class RackReservationSerializer(PrimaryModelSerializer):
class Meta:
model = RackReservation
fields = [
'id', 'url', 'display', 'rack', 'units', 'created', 'user', 'tenant', 'description', 'tags',
'id', 'url', 'display', 'rack', 'units', 'created', 'last_updated', 'user', 'tenant', 'description', 'tags',
'custom_fields',
]
@@ -913,7 +913,7 @@ class CableSerializer(PrimaryModelSerializer):
fields = [
'id', 'url', 'display', 'termination_a_type', 'termination_a_id', 'termination_a', 'termination_b_type',
'termination_b_id', 'termination_b', 'type', 'status', 'tenant', 'label', 'color', 'length', 'length_unit',
'tags', 'custom_fields',
'tags', 'custom_fields', 'created', 'last_updated',
]
def _get_termination(self, obj, side):
@@ -1007,7 +1007,10 @@ class VirtualChassisSerializer(PrimaryModelSerializer):
class Meta:
model = VirtualChassis
fields = ['id', 'url', 'display', 'name', 'domain', 'master', 'tags', 'custom_fields', 'member_count']
fields = [
'id', 'url', 'display', 'name', 'domain', 'master', 'tags', 'custom_fields', 'member_count',
'created', 'last_updated',
]
#
@@ -1026,7 +1029,10 @@ class PowerPanelSerializer(PrimaryModelSerializer):
class Meta:
model = PowerPanel
fields = ['id', 'url', 'display', 'site', 'location', 'name', 'tags', 'custom_fields', 'powerfeed_count']
fields = [
'id', 'url', 'display', 'site', 'location', 'name', 'tags', 'custom_fields', 'powerfeed_count',
'created', 'last_updated',
]
class PowerFeedSerializer(PrimaryModelSerializer, LinkTerminationSerializer, ConnectedEndpointSerializer):

View File

@@ -157,7 +157,7 @@ class SiteFilterForm(TenancyFilterForm, CustomFieldModelFilterForm):
class LocationFilterForm(TenancyFilterForm, CustomFieldModelFilterForm):
model = Location
field_groups = [
['q'],
['q', 'tag'],
['region_id', 'site_group_id', 'site_id', 'parent_id'],
['tenant_group_id', 'tenant_id'],
]

View File

@@ -19,7 +19,12 @@ __all__ = (
def get_device_name(device):
return device.name or str(device.device_type)
if device.virtual_chassis:
return f'{device.virtual_chassis.name}:{device.vc_position}'
elif device.name:
return device.name
else:
return str(device.device_type)
class RackElevationSVG:

View File

@@ -56,7 +56,7 @@ class CableTable(BaseTable):
model = Cable
fields = (
'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',
'status', 'type', 'tenant', 'color', 'length', 'tags',
'status', 'type', 'tenant', 'color', 'length', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'id', 'label', 'termination_a_parent', 'termination_a', 'termination_b_parent', 'termination_b',

View File

@@ -99,7 +99,7 @@ class DeviceRoleTable(BaseTable):
model = DeviceRole
fields = (
'pk', 'id', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'tags',
'actions',
'actions', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description')
@@ -131,7 +131,7 @@ class PlatformTable(BaseTable):
model = Platform
fields = (
'pk', 'id', 'name', 'manufacturer', 'device_count', 'vm_count', 'slug', 'napalm_driver', 'napalm_args',
'description', 'tags', 'actions',
'description', 'tags', 'actions', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'manufacturer', 'device_count', 'vm_count', 'napalm_driver', 'description',
@@ -205,7 +205,8 @@ class DeviceTable(BaseTable):
fields = (
'pk', 'id', 'name', 'status', 'tenant', 'device_role', 'manufacturer', 'device_type', 'platform', 'serial',
'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'primary_ip', 'airflow', 'primary_ip4',
'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments', 'tags',
'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments', 'tags', 'created',
'last_updated',
)
default_columns = (
'pk', 'name', 'status', 'tenant', 'site', 'location', 'rack', 'device_role', 'manufacturer', 'device_type',
@@ -311,7 +312,7 @@ class ConsolePortTable(ModularDeviceComponentTable, PathEndpointTable):
model = ConsolePort
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'speed', 'description',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'type', 'speed', 'description')
@@ -353,7 +354,7 @@ class ConsoleServerPortTable(ModularDeviceComponentTable, PathEndpointTable):
model = ConsoleServerPort
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'speed', 'description',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'type', 'speed', 'description')
@@ -396,7 +397,8 @@ class PowerPortTable(ModularDeviceComponentTable, PathEndpointTable):
model = PowerPort
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'description', 'mark_connected',
'maximum_draw', 'allocated_draw', 'cable', 'cable_color', 'link_peer', 'connection', 'tags',
'maximum_draw', 'allocated_draw', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
@@ -444,7 +446,8 @@ class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable):
model = PowerOutlet
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'description', 'power_port',
'feed_leg', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags',
'feed_leg', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'type', 'power_port', 'feed_leg', 'description')
@@ -524,6 +527,7 @@ class InterfaceTable(ModularDeviceComponentTable, BaseInterfaceTable, PathEndpoi
'mode', 'mac_address', 'wwn', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width',
'tx_power', 'description', 'mark_connected', 'cable', 'cable_color', 'wireless_link', 'wireless_lans',
'link_peer', 'connection', 'tags', 'vrf', 'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans',
'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'enabled', 'type', 'description')
@@ -594,6 +598,7 @@ class FrontPortTable(ModularDeviceComponentTable, CableTerminationTable):
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'color', 'rear_port',
'rear_port_position', 'description', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'tags',
'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'device', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description',
@@ -641,7 +646,7 @@ class RearPortTable(ModularDeviceComponentTable, CableTerminationTable):
model = RearPort
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'color', 'positions', 'description',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'tags',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'type', 'color', 'description')
@@ -691,7 +696,11 @@ class DeviceBayTable(DeviceComponentTable):
class Meta(DeviceComponentTable.Meta):
model = DeviceBay
fields = ('pk', 'id', 'name', 'device', 'label', 'status', 'installed_device', 'description', 'tags')
fields = (
'pk', 'id', 'name', 'device', 'label', 'status', 'installed_device', 'description', 'tags',
'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'status', 'installed_device', 'description')
@@ -774,7 +783,7 @@ class InventoryItemTable(DeviceComponentTable):
model = InventoryItem
fields = (
'pk', 'id', 'name', 'device', 'component', 'label', 'role', 'manufacturer', 'part_id', 'serial',
'asset_tag', 'description', 'discovered', 'tags',
'asset_tag', 'description', 'discovered', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'device', 'label', 'role', 'manufacturer', 'part_id', 'serial', 'asset_tag',
@@ -847,5 +856,5 @@ class VirtualChassisTable(BaseTable):
class Meta(BaseTable.Meta):
model = VirtualChassis
fields = ('pk', 'id', 'name', 'domain', 'master', 'member_count', 'tags')
fields = ('pk', 'id', 'name', 'domain', 'master', 'member_count', 'tags', 'created', 'last_updated',)
default_columns = ('pk', 'name', 'domain', 'master', 'member_count')

View File

@@ -53,7 +53,7 @@ class ManufacturerTable(BaseTable):
model = Manufacturer
fields = (
'pk', 'id', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug',
'actions',
'actions', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'description', 'slug',
@@ -87,7 +87,7 @@ class DeviceTypeTable(BaseTable):
model = DeviceType
fields = (
'pk', 'id', 'model', 'manufacturer', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
'airflow', 'comments', 'instance_count', 'tags',
'airflow', 'comments', 'instance_count', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'instance_count',

View File

@@ -33,7 +33,7 @@ class PowerPanelTable(BaseTable):
class Meta(BaseTable.Meta):
model = PowerPanel
fields = ('pk', 'id', 'name', 'site', 'location', 'powerfeed_count', 'tags')
fields = ('pk', 'id', 'name', 'site', 'location', 'powerfeed_count', 'tags', 'created', 'last_updated',)
default_columns = ('pk', 'name', 'site', 'location', 'powerfeed_count')
@@ -72,7 +72,7 @@ class PowerFeedTable(CableTerminationTable):
fields = (
'pk', 'id', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
'max_utilization', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'available_power',
'comments', 'tags',
'comments', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable',

View File

@@ -30,7 +30,10 @@ class RackRoleTable(BaseTable):
class Meta(BaseTable.Meta):
model = RackRole
fields = ('pk', 'id', 'name', 'rack_count', 'color', 'description', 'slug', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'rack_count', 'color', 'description', 'slug', 'tags', 'actions', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'rack_count', 'color', 'description')
@@ -86,8 +89,9 @@ class RackTable(BaseTable):
class Meta(BaseTable.Meta):
model = Rack
fields = (
'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag', 'type',
'width', 'outer_width', 'outer_depth', 'u_height', 'comments', 'device_count', 'get_utilization', 'get_power_utilization', 'tags',
'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag',
'type', 'width', 'outer_width', 'outer_depth', 'u_height', 'comments', 'device_count', 'get_utilization',
'get_power_utilization', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'u_height', 'device_count',
@@ -125,6 +129,6 @@ class RackReservationTable(BaseTable):
model = RackReservation
fields = (
'pk', 'id', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags',
'actions',
'actions', 'created', 'last_updated',
)
default_columns = ('pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'description')

View File

@@ -35,7 +35,9 @@ class RegionTable(BaseTable):
class Meta(BaseTable.Meta):
model = Region
fields = ('pk', 'id', 'name', 'slug', 'site_count', 'description', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'slug', 'site_count', 'description', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'site_count', 'description')
@@ -59,7 +61,9 @@ class SiteGroupTable(BaseTable):
class Meta(BaseTable.Meta):
model = SiteGroup
fields = ('pk', 'id', 'name', 'slug', 'site_count', 'description', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'slug', 'site_count', 'description', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'site_count', 'description')
@@ -96,7 +100,7 @@ class SiteTable(BaseTable):
fields = (
'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'asn_count', 'time_zone',
'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments', 'tags',
'actions',
'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'status', 'facility', 'region', 'group', 'tenant', 'description')
@@ -135,6 +139,6 @@ class LocationTable(BaseTable):
model = Location
fields = (
'pk', 'id', 'name', 'site', 'tenant', 'rack_count', 'device_count', 'description', 'slug', 'tags',
'actions',
'actions', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'site', 'tenant', 'rack_count', 'device_count', 'description')

View File

@@ -63,7 +63,7 @@ class WebhookSerializer(ValidatedModelSerializer):
fields = [
'id', 'url', 'display', 'content_types', 'name', 'type_create', 'type_update', 'type_delete', 'payload_url',
'enabled', 'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret',
'conditions', 'ssl_verification', 'ca_file_path',
'conditions', 'ssl_verification', 'ca_file_path', 'created', 'last_updated',
]
@@ -84,7 +84,8 @@ class CustomFieldSerializer(ValidatedModelSerializer):
model = CustomField
fields = [
'id', 'url', 'display', 'content_types', 'type', 'name', 'label', 'description', 'required', 'filter_logic',
'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices',
'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', 'created',
'last_updated',
]
@@ -102,7 +103,7 @@ class CustomLinkSerializer(ValidatedModelSerializer):
model = CustomLink
fields = [
'id', 'url', 'display', 'content_type', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name',
'button_class', 'new_window',
'button_class', 'new_window', 'created', 'last_updated',
]
@@ -120,7 +121,7 @@ class ExportTemplateSerializer(ValidatedModelSerializer):
model = ExportTemplate
fields = [
'id', 'url', 'display', 'content_type', 'name', 'description', 'template_code', 'mime_type',
'file_extension', 'as_attachment',
'file_extension', 'as_attachment', 'created', 'last_updated',
]
@@ -134,7 +135,9 @@ class TagSerializer(ValidatedModelSerializer):
class Meta:
model = Tag
fields = ['id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tagged_items']
fields = [
'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tagged_items', 'created', 'last_updated',
]
#

View File

@@ -4,7 +4,7 @@ from django.db.models import Q
from extras.choices import *
from extras.models import *
from utilities.forms import BootstrapMixin, BulkEditForm, CSVModelForm, FilterForm
from utilities.forms import BootstrapMixin, BulkEditBaseForm, CSVModelForm
__all__ = (
'CustomFieldModelCSVForm',
@@ -34,6 +34,9 @@ class CustomFieldsMixin:
raise NotImplementedError(f"{self.__class__.__name__} must specify a model class.")
return ContentType.objects.get_for_model(self.model)
def _get_custom_fields(self, content_type):
return CustomField.objects.filter(content_types=content_type)
def _get_form_field(self, customfield):
return customfield.to_form_field()
@@ -41,10 +44,7 @@ class CustomFieldsMixin:
"""
Append form fields for all CustomFields assigned to this object type.
"""
content_type = self._get_content_type()
# Append form fields; assign initial values if modifying and existing object
for customfield in CustomField.objects.filter(content_types=content_type):
for customfield in self._get_custom_fields(self._get_content_type()):
field_name = f'cf_{customfield.name}'
self.fields[field_name] = self._get_form_field(customfield)
@@ -89,40 +89,37 @@ class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelForm):
return customfield.to_form_field(for_csv_import=True)
class CustomFieldModelBulkEditForm(BulkEditForm):
class CustomFieldModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, BulkEditBaseForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def _get_form_field(self, customfield):
return customfield.to_form_field(set_initial=False, enforce_required=False)
self.custom_fields = []
self.obj_type = ContentType.objects.get_for_model(self.model)
# Add all applicable CustomFields to the form
custom_fields = CustomField.objects.filter(content_types=self.obj_type)
for cf in custom_fields:
def _append_customfield_fields(self):
"""
Append form fields for all CustomFields assigned to this object type.
"""
for customfield in self._get_custom_fields(self._get_content_type()):
# Annotate non-required custom fields as nullable
if not cf.required:
self.nullable_fields.append(cf.name)
self.fields[cf.name] = cf.to_form_field(set_initial=False, enforce_required=False)
# Annotate this as a custom field
self.custom_fields.append(cf.name)
if not customfield.required:
self.nullable_fields.append(customfield.name)
self.fields[customfield.name] = self._get_form_field(customfield)
# Annotate the field in the list of CustomField form fields
self.custom_fields[customfield.name] = customfield
class CustomFieldModelFilterForm(FilterForm):
class CustomFieldModelFilterForm(BootstrapMixin, CustomFieldsMixin, forms.Form):
q = forms.CharField(
required=False,
label='Search'
)
def __init__(self, *args, **kwargs):
self.obj_type = ContentType.objects.get_for_model(self.model)
super().__init__(*args, **kwargs)
# Add all applicable CustomFields to the form
self.custom_field_filters = []
custom_fields = CustomField.objects.filter(content_types=self.obj_type).exclude(
def _get_custom_fields(self, content_type):
return CustomField.objects.filter(content_types=content_type).exclude(
Q(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED) |
Q(type=CustomFieldTypeChoices.TYPE_JSON)
)
for cf in custom_fields:
field_name = f'cf_{cf.name}'
self.fields[field_name] = cf.to_form_field(set_initial=False, enforce_required=False)
self.custom_field_filters.append(field_name)
def _get_form_field(self, customfield):
return customfield.to_form_field(set_initial=False, enforce_required=False)

View File

@@ -58,7 +58,7 @@ class CustomFieldTable(BaseTable):
model = CustomField
fields = (
'pk', 'id', 'name', 'content_types', 'label', 'type', 'required', 'weight', 'default',
'description', 'filter_logic', 'choices',
'description', 'filter_logic', 'choices', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'content_types', 'label', 'type', 'required', 'description')
@@ -80,7 +80,7 @@ class CustomLinkTable(BaseTable):
model = CustomLink
fields = (
'pk', 'id', 'name', 'content_type', 'enabled', 'link_text', 'link_url', 'weight', 'group_name',
'button_class', 'new_window',
'button_class', 'new_window', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'content_type', 'enabled', 'group_name', 'button_class', 'new_window')
@@ -101,6 +101,7 @@ class ExportTemplateTable(BaseTable):
model = ExportTemplate
fields = (
'pk', 'id', 'name', 'content_type', 'description', 'mime_type', 'file_extension', 'as_attachment',
'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'content_type', 'description', 'mime_type', 'file_extension', 'as_attachment',
@@ -135,7 +136,7 @@ class WebhookTable(BaseTable):
model = Webhook
fields = (
'pk', 'id', 'name', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete', 'http_method',
'payload_url', 'secret', 'ssl_validation', 'ca_file_path',
'payload_url', 'secret', 'ssl_validation', 'ca_file_path', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'content_types', 'enabled', 'type_create', 'type_update', 'type_delete', 'http_method',
@@ -156,7 +157,7 @@ class TagTable(BaseTable):
class Meta(BaseTable.Meta):
model = Tag
fields = ('pk', 'id', 'name', 'items', 'slug', 'color', 'description', 'actions')
fields = ('pk', 'id', 'name', 'items', 'slug', 'color', 'description', 'created', 'last_updated', 'actions')
default_columns = ('pk', 'name', 'items', 'slug', 'color', 'description')
@@ -193,7 +194,8 @@ class ConfigContextTable(BaseTable):
model = ConfigContext
fields = (
'pk', 'id', 'name', 'weight', 'is_active', 'description', 'regions', 'sites', 'roles',
'platforms', 'cluster_types', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants',
'platforms', 'cluster_types', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'weight', 'is_active', 'description')

View File

@@ -125,11 +125,30 @@ class ASN(PrimaryModel):
verbose_name_plural = 'ASNs'
def __str__(self):
return f'AS{self.asn}'
return f'AS{self.asn_with_asdot}'
def get_absolute_url(self):
return reverse('ipam:asn', args=[self.pk])
@property
def asn_asdot(self):
"""
Return ASDOT notation for AS numbers greater than 16 bits.
"""
if self.asn > 65535:
return f'{self.asn // 65536}.{self.asn % 65536}'
return self.asn
@property
def asn_with_asdot(self):
"""
Return both plain and ASDOT notation, where applicable.
"""
if self.asn > 65535:
return f'{self.asn} ({self.asn // 65536}.{self.asn % 65536})'
else:
return self.asn
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):

View File

@@ -38,7 +38,7 @@ class FHRPGroupTable(BaseTable):
model = FHRPGroup
fields = (
'pk', 'group_id', 'protocol', 'auth_type', 'auth_key', 'description', 'ip_addresses', 'interface_count',
'tags',
'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'group_id', 'protocol', 'auth_type', 'description', 'ip_addresses', 'interface_count')

View File

@@ -91,7 +91,10 @@ class RIRTable(BaseTable):
class Meta(BaseTable.Meta):
model = RIR
fields = ('pk', 'id', 'name', 'slug', 'is_private', 'aggregate_count', 'description', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'slug', 'is_private', 'aggregate_count', 'description', 'tags', 'created',
'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'is_private', 'aggregate_count', 'description')
@@ -102,8 +105,10 @@ class RIRTable(BaseTable):
class ASNTable(BaseTable):
pk = ToggleColumn()
asn = tables.Column(
accessor=tables.A('asn_asdot'),
linkify=True
)
site_count = LinkedCountColumn(
viewname='dcim:site_list',
url_params={'asn_id': 'pk'},
@@ -112,7 +117,7 @@ class ASNTable(BaseTable):
class Meta(BaseTable.Meta):
model = ASN
fields = ('pk', 'asn', 'rir', 'site_count', 'tenant', 'description', 'actions')
fields = ('pk', 'asn', 'rir', 'site_count', 'tenant', 'description', 'created', 'last_updated', 'actions')
default_columns = ('pk', 'asn', 'rir', 'site_count', 'sites', 'tenant')
@@ -144,7 +149,10 @@ class AggregateTable(BaseTable):
class Meta(BaseTable.Meta):
model = Aggregate
fields = ('pk', 'id', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description', 'tags')
fields = (
'pk', 'id', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description', 'tags',
'created', 'last_updated',
)
default_columns = ('pk', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description')
@@ -173,7 +181,10 @@ class RoleTable(BaseTable):
class Meta(BaseTable.Meta):
model = Role
fields = ('pk', 'id', 'name', 'slug', 'prefix_count', 'vlan_count', 'description', 'weight', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'slug', 'prefix_count', 'vlan_count', 'description', 'weight', 'tags', 'created',
'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'prefix_count', 'vlan_count', 'description')
@@ -260,8 +271,8 @@ class PrefixTable(BaseTable):
class Meta(BaseTable.Meta):
model = Prefix
fields = (
'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan_group',
'vlan', 'role', 'is_pool', 'mark_utilized', 'description', 'tags',
'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site',
'vlan_group', 'vlan', 'role', 'is_pool', 'mark_utilized', 'description', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'prefix', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description',
@@ -302,7 +313,7 @@ class IPRangeTable(BaseTable):
model = IPRange
fields = (
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
'utilization', 'tags',
'utilization', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
@@ -360,7 +371,7 @@ class IPAddressTable(BaseTable):
model = IPAddress
fields = (
'pk', 'id', 'address', 'vrf', 'status', 'role', 'tenant', 'nat_inside', 'assigned', 'dns_name', 'description',
'tags',
'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'address', 'vrf', 'status', 'role', 'tenant', 'assigned', 'dns_name', 'description',

View File

@@ -45,5 +45,8 @@ class ServiceTable(BaseTable):
class Meta(BaseTable.Meta):
model = Service
fields = ('pk', 'id', 'name', 'parent', 'protocol', 'ports', 'ipaddresses', 'description', 'tags')
fields = (
'pk', 'id', 'name', 'parent', 'protocol', 'ports', 'ipaddresses', 'description', 'tags', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'parent', 'protocol', 'ports', 'description')

View File

@@ -85,7 +85,7 @@ class VLANGroupTable(BaseTable):
model = VLANGroup
fields = (
'pk', 'id', 'name', 'scope_type', 'scope', 'min_vid', 'max_vid', 'vlan_count', 'slug', 'description',
'tags', 'actions',
'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'scope_type', 'scope', 'vlan_count', 'description')
@@ -127,7 +127,10 @@ class VLANTable(BaseTable):
class Meta(BaseTable.Meta):
model = VLAN
fields = ('pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description', 'tags')
fields = (
'pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description', 'tags',
'created', 'last_updated',
)
default_columns = ('pk', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description')
row_attrs = {
'class': lambda record: 'success' if not isinstance(record, VLAN) else '',

View File

@@ -47,7 +47,8 @@ class VRFTable(BaseTable):
class Meta(BaseTable.Meta):
model = VRF
fields = (
'pk', 'id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets', 'tags',
'pk', 'id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets',
'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'rd', 'tenant', 'description')
@@ -68,5 +69,5 @@ class RouteTargetTable(BaseTable):
class Meta(BaseTable.Meta):
model = RouteTarget
fields = ('pk', 'id', 'name', 'tenant', 'description', 'tags')
fields = ('pk', 'id', 'name', 'tenant', 'description', 'tags', 'created', 'last_updated',)
default_columns = ('pk', 'name', 'tenant', 'description')

View File

@@ -287,7 +287,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
def _update_objects(self, form, request):
custom_fields = getattr(form, 'custom_fields', [])
standard_fields = [
field for field in form.fields if field not in custom_fields + ['pk']
field for field in form.fields if field not in list(custom_fields) + ['pk']
]
nullified_fields = request.POST.getlist('_nullify')
updated_objects = []

View File

@@ -24,17 +24,17 @@
{% else %}
{# List all non-customfield filters as declared in the form class #}
{% for field in filter_form.visible_fields %}
{% if not filter_form.custom_field_filters or field.name not in filter_form.custom_field_filters %}
{% if not filter_form.custom_fields or field.name not in filter_form.custom_fields %}
<div class="col col-12">
{% render_field field %}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% if filter_form.custom_field_filters %}
{% if filter_form.custom_fields %}
{# List all custom field filters #}
<hr class="card-divider mt-0" />
{% for name in filter_form.custom_field_filters %}
{% for name in filter_form.custom_fields %}
<div class="col col-12">
{% with field=filter_form|get_item:name %}
{% render_field field %}

View File

@@ -18,7 +18,7 @@
<table class="table table-hover attr-table">
<tr>
<td>AS Number</td>
<td>{{ object.asn }}</td>
<td>{{ object.asn_with_asdot }}</td>
</tr>
<tr>
<td>RIR</td>

View File

@@ -62,7 +62,9 @@ class TenantGroupTable(BaseTable):
class Meta(BaseTable.Meta):
model = TenantGroup
fields = ('pk', 'id', 'name', 'tenant_count', 'description', 'slug', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'tenant_count', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'tenant_count', 'description')
@@ -81,7 +83,7 @@ class TenantTable(BaseTable):
class Meta(BaseTable.Meta):
model = Tenant
fields = ('pk', 'id', 'name', 'slug', 'group', 'description', 'comments', 'tags')
fields = ('pk', 'id', 'name', 'slug', 'group', 'description', 'comments', 'tags', 'created', 'last_updated',)
default_columns = ('pk', 'name', 'group', 'description')
@@ -105,7 +107,9 @@ class ContactGroupTable(BaseTable):
class Meta(BaseTable.Meta):
model = ContactGroup
fields = ('pk', 'name', 'contact_count', 'description', 'slug', 'tags', 'actions')
fields = (
'pk', 'name', 'contact_count', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'contact_count', 'description')
@@ -117,7 +121,7 @@ class ContactRoleTable(BaseTable):
class Meta(BaseTable.Meta):
model = ContactRole
fields = ('pk', 'name', 'description', 'slug', 'actions')
fields = ('pk', 'name', 'description', 'slug', 'created', 'last_updated', 'actions')
default_columns = ('pk', 'name', 'description')
@@ -142,7 +146,10 @@ class ContactTable(BaseTable):
class Meta(BaseTable.Meta):
model = Contact
fields = ('pk', 'name', 'group', 'title', 'phone', 'email', 'address', 'comments', 'assignment_count', 'tags')
fields = (
'pk', 'name', 'group', 'title', 'phone', 'email', 'address', 'comments', 'assignment_count', 'tags',
'created', 'last_updated',
)
default_columns = ('pk', 'name', 'group', 'assignment_count', 'title', 'phone', 'email')

View File

@@ -3,7 +3,6 @@ import re
import yaml
from django import forms
from django.utils.translation import gettext as _
from .widgets import APISelect, APISelectMultiple, ClearableFileInput, StaticSelect
@@ -11,6 +10,7 @@ from .widgets import APISelect, APISelectMultiple, ClearableFileInput, StaticSel
__all__ = (
'BootstrapMixin',
'BulkEditForm',
'BulkEditBaseForm',
'BulkRenameForm',
'ConfirmationForm',
'CSVModelForm',
@@ -75,11 +75,10 @@ class ConfirmationForm(BootstrapMixin, ReturnURLForm):
confirm = forms.BooleanField(required=True, widget=forms.HiddenInput(), initial=True)
class BulkEditForm(BootstrapMixin, forms.Form):
class BulkEditBaseForm(forms.Form):
"""
Base form for editing multiple objects in bulk
"""
def __init__(self, model, *args, **kwargs):
super().__init__(*args, **kwargs)
self.model = model
@@ -90,6 +89,10 @@ class BulkEditForm(BootstrapMixin, forms.Form):
self.nullable_fields = self.Meta.nullable_fields
class BulkEditForm(BootstrapMixin, BulkEditBaseForm):
pass
class BulkRenameForm(BootstrapMixin, forms.Form):
"""
An extendable form to be used for renaming objects in bulk.
@@ -185,10 +188,7 @@ class FilterForm(BootstrapMixin, forms.Form):
"""
q = forms.CharField(
required=False,
widget=forms.TextInput(
attrs={'placeholder': _('All fields')}
),
label=_('Search')
label='Search'
)

View File

@@ -44,7 +44,9 @@ class ClusterTypeTable(BaseTable):
class Meta(BaseTable.Meta):
model = ClusterType
fields = ('pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'created', 'last_updated', 'tags', 'actions',
)
default_columns = ('pk', 'name', 'cluster_count', 'description')
@@ -66,7 +68,9 @@ class ClusterGroupTable(BaseTable):
class Meta(BaseTable.Meta):
model = ClusterGroup
fields = ('pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'tags', 'actions')
fields = (
'pk', 'id', 'name', 'slug', 'cluster_count', 'description', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'cluster_count', 'description')
@@ -108,7 +112,10 @@ class ClusterTable(BaseTable):
class Meta(BaseTable.Meta):
model = Cluster
fields = ('pk', 'id', 'name', 'type', 'group', 'tenant', 'site', 'comments', 'device_count', 'vm_count', 'tags')
fields = (
'pk', 'id', 'name', 'type', 'group', 'tenant', 'site', 'comments', 'device_count', 'vm_count', 'tags',
'created', 'last_updated',
)
default_columns = ('pk', 'name', 'type', 'group', 'tenant', 'site', 'device_count', 'vm_count')
@@ -149,8 +156,8 @@ class VirtualMachineTable(BaseTable):
class Meta(BaseTable.Meta):
model = VirtualMachine
fields = (
'pk', 'id', 'name', 'status', 'cluster', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'primary_ip4',
'primary_ip6', 'primary_ip', 'comments', 'tags',
'pk', 'id', 'name', 'status', 'cluster', 'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk',
'primary_ip4', 'primary_ip6', 'primary_ip', 'comments', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'status', 'cluster', 'role', 'tenant', 'vcpus', 'memory', 'disk', 'primary_ip',
@@ -177,7 +184,7 @@ class VMInterfaceTable(BaseInterfaceTable):
model = VMInterface
fields = (
'pk', 'id', 'name', 'virtual_machine', 'enabled', 'mac_address', 'mtu', 'mode', 'description', 'tags',
'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans',
'ip_addresses', 'fhrp_groups', 'untagged_vlan', 'tagged_vlans', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'virtual_machine', 'enabled', 'description')

View File

@@ -27,7 +27,9 @@ class WirelessLANGroupTable(BaseTable):
class Meta(BaseTable.Meta):
model = WirelessLANGroup
fields = ('pk', 'name', 'wirelesslan_count', 'description', 'slug', 'tags', 'actions')
fields = (
'pk', 'name', 'wirelesslan_count', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions',
)
default_columns = ('pk', 'name', 'wirelesslan_count', 'description')
@@ -50,7 +52,7 @@ class WirelessLANTable(BaseTable):
model = WirelessLAN
fields = (
'pk', 'ssid', 'group', 'description', 'vlan', 'interface_count', 'auth_type', 'auth_cipher', 'auth_psk',
'tags',
'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'ssid', 'group', 'description', 'vlan', 'auth_type', 'interface_count')
@@ -99,7 +101,7 @@ class WirelessLinkTable(BaseTable):
model = WirelessLink
fields = (
'pk', 'id', 'status', 'device_a', 'interface_a', 'device_b', 'interface_b', 'ssid', 'description',
'auth_type', 'auth_cipher', 'auth_psk', 'tags',
'auth_type', 'auth_cipher', 'auth_psk', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'id', 'status', 'device_a', 'interface_a', 'device_b', 'interface_b', 'ssid', 'auth_type',