nautobot 2.4.16__py3-none-any.whl → 2.4.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/utils.py +2 -0
- nautobot/apps/views.py +2 -0
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -8
- nautobot/circuits/templates/circuits/inc/circuit_termination_speed_fragment.html +9 -0
- nautobot/circuits/tests/integration/test_circuit.py +2 -2
- nautobot/circuits/views.py +32 -15
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +3 -3
- nautobot/cloud/views.py +7 -0
- nautobot/core/apps/__init__.py +1 -0
- nautobot/core/celery/__init__.py +2 -1
- nautobot/core/filters.py +2 -2
- nautobot/core/settings.py +1 -0
- nautobot/core/settings.yaml +9 -0
- nautobot/core/tables.py +21 -23
- nautobot/core/templates/components/breadcrumbs.html +19 -0
- nautobot/core/templates/components/panel/panel.html +1 -1
- nautobot/core/templates/generic/object_changelog.html +0 -2
- nautobot/core/templates/generic/object_list.html +15 -12
- nautobot/core/templates/generic/object_notes.html +0 -2
- nautobot/core/templates/generic/object_retrieve.html +16 -9
- nautobot/core/templates/inc/paginator.html +3 -3
- nautobot/core/templates/inc/table.html +2 -2
- nautobot/core/templatetags/helpers.py +104 -6
- nautobot/core/templatetags/ui_framework.py +40 -5
- nautobot/core/testing/filters.py +37 -21
- nautobot/core/testing/mixins.py +1 -1
- nautobot/core/testing/views.py +27 -4
- nautobot/core/tests/test_tables.py +43 -6
- nautobot/core/tests/test_templatetags_ui_framework.py +146 -0
- nautobot/core/tests/test_titles.py +2 -2
- nautobot/core/tests/test_ui.py +14 -1
- nautobot/core/tests/test_views.py +45 -0
- nautobot/core/ui/breadcrumbs.py +13 -8
- nautobot/core/ui/bulk_buttons.py +53 -53
- nautobot/core/ui/object_detail.py +52 -9
- nautobot/core/ui/titles.py +9 -5
- nautobot/core/utils/data.py +13 -0
- nautobot/core/utils/deprecation.py +2 -0
- nautobot/core/views/__init__.py +24 -3
- nautobot/core/views/generic.py +42 -17
- nautobot/core/views/mixins.py +146 -12
- nautobot/core/views/utils.py +117 -0
- nautobot/dcim/migrations/0073_alter_powerport_power_factor_and_more.py +41 -0
- nautobot/dcim/models/device_component_templates.py +4 -2
- nautobot/dcim/models/device_components.py +3 -2
- nautobot/dcim/models/devices.py +4 -0
- nautobot/dcim/tables/__init__.py +2 -0
- nautobot/dcim/tables/devices.py +24 -0
- nautobot/dcim/tables/power.py +2 -2
- nautobot/dcim/templates/dcim/device/base.html +1 -11
- nautobot/dcim/templates/dcim/device_component.html +0 -19
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -16
- nautobot/dcim/templates/dcim/rack_elevation_list.html +4 -4
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +1 -50
- nautobot/dcim/tests/test_views.py +41 -0
- nautobot/dcim/views.py +169 -39
- nautobot/extras/filters/mixins.py +1 -1
- nautobot/extras/forms/forms.py +15 -0
- nautobot/extras/models/customfields.py +45 -9
- nautobot/extras/models/groups.py +10 -1
- nautobot/extras/models/jobs.py +2 -2
- nautobot/extras/plugins/views.py +18 -5
- nautobot/extras/tables.py +4 -2
- nautobot/extras/templates/extras/configcontext_retrieve.html +1 -1
- nautobot/extras/templates/extras/configcontext_update.html +49 -49
- nautobot/extras/templates/extras/configcontextschema_retrieve.html +47 -47
- nautobot/extras/templates/extras/configcontextschema_update.html +18 -18
- nautobot/extras/templates/extras/customfield_retrieve.html +1 -128
- nautobot/extras/templates/extras/dynamicgroup.html +2 -99
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -199
- nautobot/extras/templates/extras/dynamicgroup_retrieve.html +99 -0
- nautobot/extras/templates/extras/dynamicgroup_update.html +199 -0
- nautobot/extras/templates/extras/gitrepository.html +2 -82
- nautobot/extras/templates/extras/gitrepository_object_edit.html +2 -13
- nautobot/extras/templates/extras/gitrepository_retrieve.html +82 -0
- nautobot/extras/templates/extras/gitrepository_update.html +13 -0
- nautobot/extras/templates/extras/inc/job_table.html +1 -1
- nautobot/extras/templates/extras/inc/object_contact_header.html +2 -2
- nautobot/extras/templates/extras/note_retrieve.html +1 -53
- nautobot/extras/templates/extras/plugin_detail.html +3 -7
- nautobot/extras/templates/extras/plugins_list.html +0 -2
- nautobot/extras/templates/extras/tag_retrieve.html +1 -1
- nautobot/extras/templates/extras/tag_update.html +14 -14
- nautobot/extras/templates/extras/team_retrieve.html +1 -1
- nautobot/extras/tests/test_dynamicgroups.py +73 -18
- nautobot/extras/tests/test_models.py +216 -0
- nautobot/extras/tests/test_views.py +7 -2
- nautobot/extras/urls.py +2 -94
- nautobot/extras/views.py +425 -430
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/jobs/__init__.py +10 -0
- nautobot/ipam/jobs/cleanup.py +296 -0
- nautobot/ipam/models.py +301 -178
- nautobot/ipam/querysets.py +3 -3
- nautobot/ipam/signals.py +6 -1
- nautobot/ipam/templates/ipam/inc/ipadress_edit_header.html +3 -3
- nautobot/ipam/templates/ipam/inc/toggle_available.html +2 -2
- nautobot/ipam/templates/ipam/ipaddress_assign.html +1 -1
- nautobot/ipam/templates/ipam/prefix.html +0 -8
- nautobot/ipam/templates/ipam/prefix_list.html +1 -1
- nautobot/ipam/templates/ipam/vlan_retrieve.html +1 -77
- nautobot/ipam/tests/test_api.py +5 -0
- nautobot/ipam/tests/test_jobs.py +454 -0
- nautobot/ipam/tests/test_models.py +677 -122
- nautobot/ipam/tests/test_querysets.py +46 -0
- nautobot/ipam/tests/test_views.py +40 -164
- nautobot/ipam/urls.py +0 -11
- nautobot/ipam/utils/migrations.py +1 -1
- nautobot/ipam/utils/testing.py +9 -4
- nautobot/ipam/views.py +175 -235
- nautobot/project-static/docs/404.html +9 -6
- nautobot/project-static/docs/apps/index.html +9 -6
- nautobot/project-static/docs/apps/nautobot-apps.html +9 -6
- nautobot/project-static/docs/assets/javascripts/bundle.92b07e13.min.js +16 -0
- nautobot/project-static/docs/assets/javascripts/{bundle.50899def.min.js.map → bundle.92b07e13.min.js.map} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.d50fe291.min.js → search.973d3a69.min.js} +4 -4
- nautobot/project-static/docs/assets/javascripts/workers/{search.d50fe291.min.js.map → search.973d3a69.min.js.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +10 -7
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +81 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +73 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +9 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +69 -7
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +402 -21
- nautobot/project-static/docs/development/apps/api/configuration-view.html +13 -10
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -8
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +13 -10
- nautobot/project-static/docs/development/apps/api/models/global-search.html +10 -7
- nautobot/project-static/docs/development/apps/api/models/graphql.html +18 -15
- nautobot/project-static/docs/development/apps/api/models/index.html +14 -11
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +12 -9
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +15 -12
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +9 -6
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +15 -12
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +9 -6
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -8
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +16 -13
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +12 -10305
- nautobot/project-static/docs/development/apps/api/platform-features/prepopulating-data.html +10722 -0
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +15 -12
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +14 -11
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +9 -6
- nautobot/project-static/docs/development/apps/api/prometheus.html +15 -12
- nautobot/project-static/docs/development/apps/api/setup.html +9 -6
- nautobot/project-static/docs/development/apps/api/testing.html +9 -6
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +12 -9
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +9 -6
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +9 -6
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +9 -6
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +20 -17
- nautobot/project-static/docs/development/apps/api/views/base-template.html +9 -6
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +15 -12
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +14 -11
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +9 -6
- nautobot/project-static/docs/development/apps/api/views/index.html +9 -6
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +10 -7
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +24 -21
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +12 -9
- nautobot/project-static/docs/development/apps/api/views/notes.html +10 -7
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +19 -16
- nautobot/project-static/docs/development/apps/api/views/urls.html +11 -8
- nautobot/project-static/docs/development/apps/index.html +9 -6
- nautobot/project-static/docs/development/apps/migration/code-updates.html +19 -16
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +9 -6
- nautobot/project-static/docs/development/apps/migration/from-v1.html +9 -6
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +22 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +9 -6
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +9 -6
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +9 -6
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9 -6
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +14 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +27 -24
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +20 -17
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +20 -17
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +9 -6
- nautobot/project-static/docs/development/core/application-registry.html +23 -20
- nautobot/project-static/docs/development/core/best-practices.html +23 -20
- nautobot/project-static/docs/development/core/bootstrap-ui.html +9 -6
- nautobot/project-static/docs/development/core/caching.html +9 -6
- nautobot/project-static/docs/development/core/controllers.html +9 -6
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +10 -7
- nautobot/project-static/docs/development/core/generic-views.html +9 -6
- nautobot/project-static/docs/development/core/getting-started.html +9 -21
- nautobot/project-static/docs/development/core/homepage.html +12 -9
- nautobot/project-static/docs/development/core/index.html +9 -6
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9 -6
- nautobot/project-static/docs/development/core/model-checklist.html +9 -6
- nautobot/project-static/docs/development/core/model-features.html +11 -8
- nautobot/project-static/docs/development/core/natural-keys.html +21 -18
- nautobot/project-static/docs/development/core/navigation-menu.html +10 -7
- nautobot/project-static/docs/development/core/release-checklist.html +9 -6
- nautobot/project-static/docs/development/core/role-internals.html +9 -6
- nautobot/project-static/docs/development/core/settings.html +9 -6
- nautobot/project-static/docs/development/core/style-guide.html +32 -29
- nautobot/project-static/docs/development/core/templates.html +9 -6
- nautobot/project-static/docs/development/core/testing.html +10 -7
- nautobot/project-static/docs/development/core/ui-component-framework.html +42 -44
- nautobot/project-static/docs/development/core/user-preferences.html +9 -6
- nautobot/project-static/docs/development/index.html +9 -6
- nautobot/project-static/docs/development/jobs/getting-started.html +13 -10
- nautobot/project-static/docs/development/jobs/index.html +9 -6
- nautobot/project-static/docs/development/jobs/installation.html +23 -20
- nautobot/project-static/docs/development/jobs/job-extensions.html +25 -22
- nautobot/project-static/docs/development/jobs/job-logging.html +12 -9
- nautobot/project-static/docs/development/jobs/job-patterns.html +45 -42
- nautobot/project-static/docs/development/jobs/job-structure.html +53 -50
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +23 -20
- nautobot/project-static/docs/development/jobs/testing.html +14 -11
- nautobot/project-static/docs/index.html +9 -6
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +9 -6
- nautobot/project-static/docs/overview/design_philosophy.html +9 -6
- nautobot/project-static/docs/release-notes/index.html +9 -6
- nautobot/project-static/docs/release-notes/version-1.0.html +9 -6
- nautobot/project-static/docs/release-notes/version-1.1.html +9 -6
- nautobot/project-static/docs/release-notes/version-1.2.html +10 -7
- nautobot/project-static/docs/release-notes/version-1.3.html +9 -6
- nautobot/project-static/docs/release-notes/version-1.4.html +9 -6
- nautobot/project-static/docs/release-notes/version-1.5.html +13 -10
- nautobot/project-static/docs/release-notes/version-1.6.html +9 -6
- nautobot/project-static/docs/release-notes/version-2.0.html +9 -6
- nautobot/project-static/docs/release-notes/version-2.1.html +9 -6
- nautobot/project-static/docs/release-notes/version-2.2.html +9 -6
- nautobot/project-static/docs/release-notes/version-2.3.html +9 -6
- nautobot/project-static/docs/release-notes/version-2.4.html +489 -6
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +301 -301
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +15 -12
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +9 -6
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +16 -13
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +9 -6
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +9 -6
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +38 -8
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +9 -6
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +16 -13
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/index.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +9 -6
- nautobot/project-static/docs/user-guide/administration/installation/services.html +12 -9
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +13 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +10 -7
- nautobot/project-static/docs/user-guide/administration/security/index.html +9 -6
- nautobot/project-static/docs/user-guide/administration/security/notices.html +9 -6
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +9 -6
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +10 -7
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +9 -6
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +15 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +13 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +41 -41
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +197 -54
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9 -6
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +13 -10
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +9 -6
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9 -6
- nautobot/project-static/docs/user-guide/index.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +10 -7
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -8
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +12 -9
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -8
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +9 -6
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +9 -6
- nautobot/project-static/fonts/UFL.txt +96 -96
- nautobot/project-static/img/nautobot_icon.svg +32 -34
- nautobot/project-static/js/forms.js +35 -2
- nautobot/project-static/js/table_sorting_indicator.js +0 -2
- nautobot/virtualization/filters.py +7 -0
- {nautobot-2.4.16.dist-info → nautobot-2.4.18.dist-info}/METADATA +8 -8
- {nautobot-2.4.16.dist-info → nautobot-2.4.18.dist-info}/RECORD +431 -421
- nautobot/core/templates/inc/breadcrumbs.html +0 -14
- nautobot/project-static/docs/assets/javascripts/bundle.50899def.min.js +0 -16
- nautobot/project-static/docs/requirements.txt +0 -14
- {nautobot-2.4.16.dist-info → nautobot-2.4.18.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.16.dist-info → nautobot-2.4.18.dist-info}/NOTICE +0 -0
- {nautobot-2.4.16.dist-info → nautobot-2.4.18.dist-info}/WHEEL +0 -0
- {nautobot-2.4.16.dist-info → nautobot-2.4.18.dist-info}/entry_points.txt +0 -0
nautobot/core/views/generic.py
CHANGED
|
@@ -48,7 +48,12 @@ from nautobot.core.utils.requests import (
|
|
|
48
48
|
get_filterable_params_from_filter_params,
|
|
49
49
|
normalize_querydict,
|
|
50
50
|
)
|
|
51
|
-
from nautobot.core.views.mixins import
|
|
51
|
+
from nautobot.core.views.mixins import (
|
|
52
|
+
BulkEditAndBulkDeleteModelMixin,
|
|
53
|
+
GetReturnURLMixin,
|
|
54
|
+
ObjectPermissionRequiredMixin,
|
|
55
|
+
UIComponentsMixin,
|
|
56
|
+
)
|
|
52
57
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
53
58
|
from nautobot.core.views.utils import (
|
|
54
59
|
check_filter_for_display,
|
|
@@ -63,7 +68,7 @@ from nautobot.core.views.utils import (
|
|
|
63
68
|
from nautobot.extras.models import ExportTemplate, SavedView, UserSavedViewAssociation
|
|
64
69
|
|
|
65
70
|
|
|
66
|
-
class GenericView(LoginRequiredMixin, View):
|
|
71
|
+
class GenericView(LoginRequiredMixin, UIComponentsMixin, View):
|
|
67
72
|
"""
|
|
68
73
|
Base class for non-object-related views.
|
|
69
74
|
|
|
@@ -71,7 +76,7 @@ class GenericView(LoginRequiredMixin, View):
|
|
|
71
76
|
"""
|
|
72
77
|
|
|
73
78
|
|
|
74
|
-
class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
79
|
+
class ObjectView(ObjectPermissionRequiredMixin, UIComponentsMixin, View):
|
|
75
80
|
"""
|
|
76
81
|
Retrieve a single object for display.
|
|
77
82
|
|
|
@@ -115,21 +120,28 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
|
115
120
|
Generic GET handler for accessing an object.
|
|
116
121
|
"""
|
|
117
122
|
instance = get_object_or_404(self.queryset, **kwargs)
|
|
123
|
+
model = self.queryset.model
|
|
118
124
|
content_type = ContentType.objects.get_for_model(self.queryset.model)
|
|
119
125
|
context = {
|
|
120
126
|
"object": instance,
|
|
121
127
|
"content_type": content_type,
|
|
122
|
-
"verbose_name":
|
|
123
|
-
"verbose_name_plural":
|
|
128
|
+
"verbose_name": model._meta.verbose_name,
|
|
129
|
+
"verbose_name_plural": model._meta.verbose_name_plural,
|
|
124
130
|
"object_detail_content": self.object_detail_content,
|
|
131
|
+
"breadcrumbs": self.get_breadcrumbs(model, view_type=""),
|
|
125
132
|
**common_detail_view_context(request, instance),
|
|
126
133
|
**self.get_extra_context(request, instance),
|
|
127
134
|
}
|
|
128
135
|
|
|
136
|
+
# Some of the legacy views overriding title in `get_extra_context` method.
|
|
137
|
+
# But if not, we will generate the default `title` using the default `Titles` class or one set in class under `view_titles`.
|
|
138
|
+
if context.get("title") is None:
|
|
139
|
+
context["title"] = self.get_view_titles(model, view_type="").render(context)
|
|
140
|
+
|
|
129
141
|
return render(request, self.get_template_name(), context)
|
|
130
142
|
|
|
131
143
|
|
|
132
|
-
class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
144
|
+
class ObjectListView(ObjectPermissionRequiredMixin, UIComponentsMixin, View):
|
|
133
145
|
"""
|
|
134
146
|
List a series of objects.
|
|
135
147
|
|
|
@@ -378,11 +390,13 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
378
390
|
"dynamic_filter_form": dynamic_filter_form,
|
|
379
391
|
"search_form": search_form,
|
|
380
392
|
"list_url": list_url,
|
|
381
|
-
"title": bettertitle(model._meta.verbose_name_plural),
|
|
382
393
|
"new_changes_not_applied": new_changes_not_applied,
|
|
383
394
|
"current_saved_view": current_saved_view,
|
|
384
395
|
"saved_views": saved_views,
|
|
385
396
|
"model": model,
|
|
397
|
+
"verbose_name_plural": model._meta.verbose_name_plural,
|
|
398
|
+
"view_action": "list",
|
|
399
|
+
"breadcrumbs": self.get_breadcrumbs(model),
|
|
386
400
|
}
|
|
387
401
|
|
|
388
402
|
# `extra_context()` would require `request` access, however `request` parameter cannot simply be
|
|
@@ -392,6 +406,11 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
392
406
|
setattr(self, "request", request)
|
|
393
407
|
context.update(self.extra_context())
|
|
394
408
|
|
|
409
|
+
# Some of the legacy views overriding title in `extra_context` method.
|
|
410
|
+
# But if not, we will generate the default `title` using the default `Titles` class or one set in class under `view_titles`.
|
|
411
|
+
if context.get("title") is None:
|
|
412
|
+
context["title"] = self.get_view_titles(model).render(context)
|
|
413
|
+
|
|
395
414
|
return render(request, self.template_name, context)
|
|
396
415
|
|
|
397
416
|
def alter_queryset(self, request):
|
|
@@ -402,7 +421,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
402
421
|
return {}
|
|
403
422
|
|
|
404
423
|
|
|
405
|
-
class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
424
|
+
class ObjectEditView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
406
425
|
"""
|
|
407
426
|
Create or edit a single object.
|
|
408
427
|
|
|
@@ -550,7 +569,7 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
550
569
|
)
|
|
551
570
|
|
|
552
571
|
|
|
553
|
-
class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
572
|
+
class ObjectDeleteView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
554
573
|
"""
|
|
555
574
|
Delete a single object.
|
|
556
575
|
|
|
@@ -627,7 +646,7 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
627
646
|
)
|
|
628
647
|
|
|
629
648
|
|
|
630
|
-
class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
649
|
+
class BulkCreateView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
631
650
|
"""
|
|
632
651
|
Create new objects in bulk.
|
|
633
652
|
|
|
@@ -741,7 +760,7 @@ class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
741
760
|
)
|
|
742
761
|
|
|
743
762
|
|
|
744
|
-
class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
763
|
+
class ObjectImportView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
745
764
|
"""
|
|
746
765
|
Import a single object (YAML or JSON format).
|
|
747
766
|
|
|
@@ -888,7 +907,9 @@ class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
888
907
|
)
|
|
889
908
|
|
|
890
909
|
|
|
891
|
-
class BulkImportView(
|
|
910
|
+
class BulkImportView(
|
|
911
|
+
GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View
|
|
912
|
+
): # 3.0 TODO: remove as it's no longer used
|
|
892
913
|
"""
|
|
893
914
|
Import objects in bulk (CSV format).
|
|
894
915
|
|
|
@@ -997,7 +1018,9 @@ class BulkImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): #
|
|
|
997
1018
|
)
|
|
998
1019
|
|
|
999
1020
|
|
|
1000
|
-
class BulkEditView(
|
|
1021
|
+
class BulkEditView(
|
|
1022
|
+
GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, BulkEditAndBulkDeleteModelMixin, View
|
|
1023
|
+
):
|
|
1001
1024
|
"""
|
|
1002
1025
|
Edit objects in bulk.
|
|
1003
1026
|
|
|
@@ -1093,7 +1116,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAnd
|
|
|
1093
1116
|
return {}
|
|
1094
1117
|
|
|
1095
1118
|
|
|
1096
|
-
class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1119
|
+
class BulkRenameView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
1097
1120
|
"""
|
|
1098
1121
|
An extendable view for renaming objects in bulk.
|
|
1099
1122
|
"""
|
|
@@ -1193,7 +1216,9 @@ class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
1193
1216
|
return ""
|
|
1194
1217
|
|
|
1195
1218
|
|
|
1196
|
-
class BulkDeleteView(
|
|
1219
|
+
class BulkDeleteView(
|
|
1220
|
+
GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, BulkEditAndBulkDeleteModelMixin, View
|
|
1221
|
+
):
|
|
1197
1222
|
"""
|
|
1198
1223
|
Delete objects in bulk.
|
|
1199
1224
|
|
|
@@ -1304,7 +1329,7 @@ class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditA
|
|
|
1304
1329
|
|
|
1305
1330
|
|
|
1306
1331
|
# TODO: Replace with BulkCreateView
|
|
1307
|
-
class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1332
|
+
class ComponentCreateView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
1308
1333
|
"""
|
|
1309
1334
|
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
|
1310
1335
|
"""
|
|
@@ -1410,7 +1435,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
|
1410
1435
|
)
|
|
1411
1436
|
|
|
1412
1437
|
|
|
1413
|
-
class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1438
|
+
class BulkComponentCreateView(GetReturnURLMixin, UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
1414
1439
|
"""
|
|
1415
1440
|
Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines.
|
|
1416
1441
|
"""
|
nautobot/core/views/mixins.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import ClassVar, Optional
|
|
2
|
+
from typing import ClassVar, Optional, Type, Union
|
|
3
3
|
|
|
4
4
|
from django.contrib import messages
|
|
5
5
|
from django.contrib.auth.mixins import AccessMixin
|
|
@@ -12,7 +12,7 @@ from django.core.exceptions import (
|
|
|
12
12
|
ValidationError,
|
|
13
13
|
)
|
|
14
14
|
from django.db import transaction
|
|
15
|
-
from django.db.models import ManyToManyField, ProtectedError, Q
|
|
15
|
+
from django.db.models import ManyToManyField, Model, ProtectedError, Q
|
|
16
16
|
from django.forms import Form, ModelMultipleChoiceField, MultipleHiddenInput
|
|
17
17
|
from django.http import HttpResponse
|
|
18
18
|
from django.shortcuts import get_object_or_404, redirect
|
|
@@ -217,10 +217,152 @@ class GetReturnURLMixin:
|
|
|
217
217
|
return reverse("home")
|
|
218
218
|
|
|
219
219
|
|
|
220
|
+
class UIComponentsMixin:
|
|
221
|
+
"""
|
|
222
|
+
Mixin that resolves UI components (e.g., breadcrumbs, titles) either from:
|
|
223
|
+
1) the current view class (preferred),
|
|
224
|
+
2) a related view class for a given model (via `lookup.get_view_for_model()`),
|
|
225
|
+
3) or a default component class.
|
|
226
|
+
|
|
227
|
+
The public helpers (`get_view_titles()`, `get_breadcrumbs()`) return concrete
|
|
228
|
+
component *instances* ready to use in renderers/templates.
|
|
229
|
+
|
|
230
|
+
It should be used in views that use the `nautobot.apps.views.GenericView` and standard Nautobot templates.
|
|
231
|
+
|
|
232
|
+
Example usage:
|
|
233
|
+
```
|
|
234
|
+
def get(self, request, *args, **kwargs):
|
|
235
|
+
context = {
|
|
236
|
+
...
|
|
237
|
+
"breadcrumbs": self.get_breadcrumbs(model),
|
|
238
|
+
}
|
|
239
|
+
context["title"] = self.get_view_titles(model).render(context)
|
|
240
|
+
|
|
241
|
+
return render(
|
|
242
|
+
request,
|
|
243
|
+
"extras/plugins_list.html",
|
|
244
|
+
context,
|
|
245
|
+
)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Attributes:
|
|
249
|
+
breadcrumbs (ClassVar[Optional[Breadcrumbs]]): Optional component declared on the view class. May be:
|
|
250
|
+
- `None` (no local definition, fall back),
|
|
251
|
+
- a component *class* (will be instantiated),
|
|
252
|
+
- or a pre-instantiated component (returned as-is).
|
|
253
|
+
view_titles (ClassVar[Optional[Titles]]): Same contract as `breadcrumbs`,
|
|
254
|
+
but for titles.
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
breadcrumbs: ClassVar[Optional[Breadcrumbs]] = None
|
|
258
|
+
view_titles: ClassVar[Optional[Titles]] = None
|
|
259
|
+
|
|
260
|
+
def get_view_titles(self, model: Union[None, str, Type[Model], Model] = None, view_type: str = "List") -> Titles:
|
|
261
|
+
"""
|
|
262
|
+
Resolve and return the `Titles` component instance.
|
|
263
|
+
|
|
264
|
+
Resolution order:
|
|
265
|
+
1) If `self.view_titles` is set on the current view, use it.
|
|
266
|
+
2) Else, if `model` is provided, copy the `view_titles` from the view
|
|
267
|
+
class associated with that model via `lookup.get_view_for_model(model, action)`.
|
|
268
|
+
3) Else, instantiate and return the default `Titles()`.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
model: A Django model **class**, **instance**, dotted name string, or `None`.
|
|
272
|
+
Passed to `lookup.get_view_for_model()` to find the related view class.
|
|
273
|
+
If `None`, only local/default resolution is used.
|
|
274
|
+
view_type: Logical view type used by `lookup.get_view_for_model()` (e.g., `"List"` or empty to construct `"DeviceView"` string).
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Titles: A concrete `Titles` component instance ready to use.
|
|
278
|
+
"""
|
|
279
|
+
return self._resolve_component("view_titles", Titles, model, view_type)
|
|
280
|
+
|
|
281
|
+
def get_breadcrumbs(
|
|
282
|
+
self, model: Union[None, str, Type[Model], Model] = None, view_type: str = "List"
|
|
283
|
+
) -> Breadcrumbs:
|
|
284
|
+
"""
|
|
285
|
+
Resolve and return the `Breadcrumbs` component instance.
|
|
286
|
+
|
|
287
|
+
Resolution order mirrors `get_view_titles()`:
|
|
288
|
+
1) Use `self.breadcrumbs` if set locally.
|
|
289
|
+
2) Else, if `model` is provided, copy the `breadcrumbs` from the view
|
|
290
|
+
class associated with that model via `lookup.get_view_for_model(model, action)`.
|
|
291
|
+
3) Else return a new default `Breadcrumbs()`.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
model: A Django model **class**, **instance**, dotted name string, or `None`.
|
|
295
|
+
Passed to `lookup.get_view_for_model()` to find the related view class.
|
|
296
|
+
If `None`, only local/default resolution is used.
|
|
297
|
+
view_type: Logical view type used by `lookup.get_view_for_model()` (e.g., `"List"` or empty to construct `"DeviceView"` string).
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
Breadcrumbs: A concrete `Breadcrumbs` component instance.
|
|
301
|
+
"""
|
|
302
|
+
return self._resolve_component("breadcrumbs", Breadcrumbs, model, view_type)
|
|
303
|
+
|
|
304
|
+
def _resolve_component(
|
|
305
|
+
self,
|
|
306
|
+
attr_name: str,
|
|
307
|
+
default_cls: Type[Union[Breadcrumbs, Titles]],
|
|
308
|
+
model: Union[None, str, Type[Model], Model] = None,
|
|
309
|
+
view_type: str = "List",
|
|
310
|
+
) -> Union[Breadcrumbs, Titles]:
|
|
311
|
+
"""
|
|
312
|
+
Resolve a UI component by name.
|
|
313
|
+
|
|
314
|
+
Return local view's attribute defined via `attr_name` or
|
|
315
|
+
the `attr_name` defined on the view class for model via lookup.get_view_for_model(model, view_type) or
|
|
316
|
+
instantiates `default_cls`.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
attr_name (str): Attribute to resolve (e.g., "breadcrumbs").
|
|
320
|
+
default_cls: Default Breadcrumbs/Title class to instantiate if not found.
|
|
321
|
+
model (Union[None, str, Type[Model], Model]): Django model (class/instance/dotted string) to locate a related view class.
|
|
322
|
+
view_type (str): View type for lookup (e.g., "List", or empty to resolve like "DeviceView").
|
|
323
|
+
Returns:
|
|
324
|
+
Breadcrumbs/Title instance.
|
|
325
|
+
"""
|
|
326
|
+
local = getattr(self, attr_name, None)
|
|
327
|
+
if local is not None:
|
|
328
|
+
return self._instantiate_if_needed(local, default_cls)
|
|
329
|
+
|
|
330
|
+
if model is not None:
|
|
331
|
+
view_class = lookup.get_view_for_model(model, view_type)
|
|
332
|
+
view_component = getattr(view_class, attr_name, None)
|
|
333
|
+
return self._instantiate_if_needed(view_component, default_cls)
|
|
334
|
+
|
|
335
|
+
return default_cls()
|
|
336
|
+
|
|
337
|
+
@staticmethod
|
|
338
|
+
def _instantiate_if_needed(
|
|
339
|
+
attr: Union[None, Type[Union[Breadcrumbs, Titles]], Breadcrumbs, Titles],
|
|
340
|
+
default_cls: Type[Union[Breadcrumbs, Titles]],
|
|
341
|
+
) -> Union[Breadcrumbs, Titles]:
|
|
342
|
+
"""
|
|
343
|
+
Normalize a value into a component instance.
|
|
344
|
+
|
|
345
|
+
If attr is None - return default_cls().
|
|
346
|
+
If attr is a class - instantiate it.
|
|
347
|
+
Otherwise, return as is.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
attr: None, a Breadcrumbs/Title class or an instance.
|
|
351
|
+
default_cls: Fallback class to instantiate when attr is None.
|
|
352
|
+
Returns:
|
|
353
|
+
Breadcrumbs/Title instance.
|
|
354
|
+
"""
|
|
355
|
+
if attr is None:
|
|
356
|
+
return default_cls()
|
|
357
|
+
if isinstance(attr, type):
|
|
358
|
+
return attr()
|
|
359
|
+
return attr
|
|
360
|
+
|
|
361
|
+
|
|
220
362
|
@extend_schema(exclude=True)
|
|
221
|
-
class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormView):
|
|
363
|
+
class NautobotViewSetMixin(GenericViewSet, UIComponentsMixin, AccessMixin, GetReturnURLMixin, FormView):
|
|
222
364
|
"""
|
|
223
|
-
NautobotViewSetMixin is an aggregation of various mixins from DRF, Django and Nautobot to
|
|
365
|
+
NautobotViewSetMixin is an aggregation of various mixins from DRF, Django and Nautobot to achieve the desired behavior pattern for NautobotUIViewSet
|
|
224
366
|
"""
|
|
225
367
|
|
|
226
368
|
renderer_classes = [NautobotHTMLRenderer]
|
|
@@ -244,14 +386,6 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
|
|
|
244
386
|
# custom view attributes used for permission checks and handling
|
|
245
387
|
custom_view_base_action = None
|
|
246
388
|
custom_view_additional_permissions = None
|
|
247
|
-
view_titles = None
|
|
248
|
-
breadcrumbs = None
|
|
249
|
-
|
|
250
|
-
def get_view_titles(self):
|
|
251
|
-
return self.instantiate_if_needed(self.view_titles, Titles)
|
|
252
|
-
|
|
253
|
-
def get_breadcrumbs(self):
|
|
254
|
-
return self.instantiate_if_needed(self.breadcrumbs, Breadcrumbs)
|
|
255
389
|
|
|
256
390
|
@staticmethod
|
|
257
391
|
def instantiate_if_needed(attr, default_cls):
|
nautobot/core/views/utils.py
CHANGED
|
@@ -2,12 +2,16 @@ import datetime
|
|
|
2
2
|
from io import BytesIO
|
|
3
3
|
import urllib.parse
|
|
4
4
|
|
|
5
|
+
from django.conf import settings
|
|
5
6
|
from django.contrib import messages
|
|
7
|
+
from django.core.cache import cache
|
|
6
8
|
from django.core.exceptions import FieldError, ValidationError
|
|
7
9
|
from django.db.models import ForeignKey
|
|
8
10
|
from django.utils.html import format_html, format_html_join
|
|
9
11
|
from django.utils.safestring import mark_safe
|
|
10
12
|
from django_tables2 import RequestConfig
|
|
13
|
+
from prometheus_client import REGISTRY
|
|
14
|
+
from prometheus_client.utils import floatToGoString
|
|
11
15
|
from rest_framework import exceptions, serializers
|
|
12
16
|
|
|
13
17
|
from nautobot.core.api.fields import ChoiceField, ContentTypeField, TimeZoneSerializerField
|
|
@@ -20,6 +24,11 @@ from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
|
20
24
|
from nautobot.extras.models import SavedView
|
|
21
25
|
from nautobot.extras.tables import AssociatedContactsTable, DynamicGroupTable, ObjectMetadataTable
|
|
22
26
|
|
|
27
|
+
METRICS_CACHE_KEY = "nautobot_app_metrics_cache"
|
|
28
|
+
always_generated_metrics = [
|
|
29
|
+
"nautobot_app_metrics_processing_ms" # Always generate this metric to track the processing time of Nautobot App metrics, improved with caching.
|
|
30
|
+
]
|
|
31
|
+
|
|
23
32
|
|
|
24
33
|
def check_filter_for_display(filters, field_name, values):
|
|
25
34
|
"""
|
|
@@ -399,3 +408,111 @@ def get_saved_views_for_user(user, list_url):
|
|
|
399
408
|
return shared_saved_views | user_owned_saved_views
|
|
400
409
|
|
|
401
410
|
return shared_saved_views
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def is_metrics_experimental_caching_enabled():
|
|
414
|
+
"""Return True if METRICS_EXPERIMENTAL_CACHING_DURATION is set to a positive integer."""
|
|
415
|
+
return settings.METRICS_EXPERIMENTAL_CACHING_DURATION > 0
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def generate_latest_with_cache(registry=REGISTRY):
|
|
419
|
+
"""A vendored version of prometheus_client.generate_latest that caches Nautobot App metrics."""
|
|
420
|
+
|
|
421
|
+
def sample_line(line):
|
|
422
|
+
if line.labels:
|
|
423
|
+
labelstr = "{{{0}}}".format(
|
|
424
|
+
",".join(
|
|
425
|
+
[
|
|
426
|
+
'{}="{}"'.format(k, v.replace("\\", r"\\").replace("\n", r"\n").replace('"', r"\""))
|
|
427
|
+
for k, v in sorted(line.labels.items())
|
|
428
|
+
]
|
|
429
|
+
)
|
|
430
|
+
)
|
|
431
|
+
else:
|
|
432
|
+
labelstr = ""
|
|
433
|
+
timestamp = ""
|
|
434
|
+
if line.timestamp is not None:
|
|
435
|
+
# Convert to milliseconds.
|
|
436
|
+
timestamp = f" {int(float(line.timestamp) * 1000):d}"
|
|
437
|
+
return f"{line.name}{labelstr} {floatToGoString(line.value)}{timestamp}\n"
|
|
438
|
+
|
|
439
|
+
cached_lines = []
|
|
440
|
+
output = []
|
|
441
|
+
# NOTE: In the original prometheus_client code the lines are written to output directly,
|
|
442
|
+
# here we are going to cache some lines so we need to build each metric's output separately.
|
|
443
|
+
# So instead of `output.append(line)` we do
|
|
444
|
+
# `this_metric_output.append(line)` and then `output.extend(this_metric_output)`
|
|
445
|
+
for metric in registry.collect():
|
|
446
|
+
this_metric_output = []
|
|
447
|
+
try:
|
|
448
|
+
mname = metric.name
|
|
449
|
+
mtype = metric.type
|
|
450
|
+
# Munging from OpenMetrics into Prometheus format.
|
|
451
|
+
if mtype == "counter":
|
|
452
|
+
mname = mname + "_total"
|
|
453
|
+
elif mtype == "info":
|
|
454
|
+
mname = mname + "_info"
|
|
455
|
+
mtype = "gauge"
|
|
456
|
+
elif mtype == "stateset":
|
|
457
|
+
mtype = "gauge"
|
|
458
|
+
elif mtype == "gaugehistogram":
|
|
459
|
+
# A gauge histogram is really a gauge,
|
|
460
|
+
# but this captures the structure better.
|
|
461
|
+
mtype = "histogram"
|
|
462
|
+
elif mtype == "unknown":
|
|
463
|
+
mtype = "untyped"
|
|
464
|
+
|
|
465
|
+
this_metric_output.append(
|
|
466
|
+
"# HELP {} {}\n".format(mname, metric.documentation.replace("\\", r"\\").replace("\n", r"\n"))
|
|
467
|
+
)
|
|
468
|
+
this_metric_output.append(f"# TYPE {mname} {mtype}\n")
|
|
469
|
+
|
|
470
|
+
om_samples = {}
|
|
471
|
+
for s in metric.samples:
|
|
472
|
+
for suffix in ["_created", "_gsum", "_gcount"]:
|
|
473
|
+
if s.name == metric.name + suffix:
|
|
474
|
+
# OpenMetrics specific sample, put in a gauge at the end.
|
|
475
|
+
om_samples.setdefault(suffix, []).append(sample_line(s))
|
|
476
|
+
break
|
|
477
|
+
else:
|
|
478
|
+
this_metric_output.append(sample_line(s))
|
|
479
|
+
except Exception as exception:
|
|
480
|
+
exception.args = (exception.args or ("",)) + (metric,)
|
|
481
|
+
raise
|
|
482
|
+
|
|
483
|
+
for suffix, lines in sorted(om_samples.items()):
|
|
484
|
+
this_metric_output.append(
|
|
485
|
+
"# HELP {}{} {}\n".format(
|
|
486
|
+
metric.name, suffix, metric.documentation.replace("\\", r"\\").replace("\n", r"\n")
|
|
487
|
+
)
|
|
488
|
+
)
|
|
489
|
+
this_metric_output.append(f"# TYPE {metric.name}{suffix} gauge\n")
|
|
490
|
+
this_metric_output.extend(lines)
|
|
491
|
+
|
|
492
|
+
# BEGIN Nautobot-specific logic
|
|
493
|
+
# If the metric name starts with nautobot_, we cache the lines
|
|
494
|
+
if metric.name.startswith("nautobot_") and metric.name not in always_generated_metrics:
|
|
495
|
+
cached_lines.extend(this_metric_output)
|
|
496
|
+
# END Nautobot-specific logic
|
|
497
|
+
|
|
498
|
+
# Always add the metric output to the final output
|
|
499
|
+
output.extend(this_metric_output)
|
|
500
|
+
|
|
501
|
+
# BEGIN Nautobot-specific logic
|
|
502
|
+
# Add in any previously cached metrics.
|
|
503
|
+
# Note that this is mutually-exclusive with the above block, that is to say,
|
|
504
|
+
# either cached_lines will be populated OR collector.local_cache will be populated,
|
|
505
|
+
# never both at the same time.
|
|
506
|
+
for collector in registry._collector_to_names:
|
|
507
|
+
# This is to avoid a race condition where between the time to collect the metrics and
|
|
508
|
+
# the time to generate the output, the cache is expired and we miss some metrics.
|
|
509
|
+
if hasattr(collector, "local_cache") and collector.local_cache:
|
|
510
|
+
output.extend(collector.local_cache)
|
|
511
|
+
del collector.local_cache # avoid re-using stale data on next call
|
|
512
|
+
|
|
513
|
+
# If we have any cached lines, and the cache is empty or expired, update the cache.
|
|
514
|
+
if cached_lines and not cache.get(METRICS_CACHE_KEY):
|
|
515
|
+
cache.set(METRICS_CACHE_KEY, cached_lines, timeout=settings.METRICS_EXPERIMENTAL_CACHING_DURATION)
|
|
516
|
+
# END Nautobot-specific logic
|
|
517
|
+
|
|
518
|
+
return "".join(output).encode("utf-8")
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Generated by Django 4.2.23 on 2025-08-22 21:03
|
|
2
|
+
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
|
|
5
|
+
import django.core.validators
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
dependencies = [
|
|
11
|
+
("dcim", "0072_alter_powerfeed_options_and_more"),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.AlterField(
|
|
16
|
+
model_name="powerport",
|
|
17
|
+
name="power_factor",
|
|
18
|
+
field=models.DecimalField(
|
|
19
|
+
decimal_places=2,
|
|
20
|
+
default=Decimal("0.95"),
|
|
21
|
+
max_digits=4,
|
|
22
|
+
validators=[
|
|
23
|
+
django.core.validators.MinValueValidator(Decimal("0.01")),
|
|
24
|
+
django.core.validators.MaxValueValidator(Decimal("1.00")),
|
|
25
|
+
],
|
|
26
|
+
),
|
|
27
|
+
),
|
|
28
|
+
migrations.AlterField(
|
|
29
|
+
model_name="powerporttemplate",
|
|
30
|
+
name="power_factor",
|
|
31
|
+
field=models.DecimalField(
|
|
32
|
+
decimal_places=2,
|
|
33
|
+
default=Decimal("0.95"),
|
|
34
|
+
max_digits=4,
|
|
35
|
+
validators=[
|
|
36
|
+
django.core.validators.MinValueValidator(Decimal("0.01")),
|
|
37
|
+
django.core.validators.MaxValueValidator(Decimal("1.00")),
|
|
38
|
+
],
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
|
|
1
3
|
from django.contrib.contenttypes.models import ContentType
|
|
2
4
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
3
5
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
|
@@ -252,8 +254,8 @@ class PowerPortTemplate(ModularComponentTemplateModel):
|
|
|
252
254
|
power_factor = models.DecimalField(
|
|
253
255
|
max_digits=4,
|
|
254
256
|
decimal_places=2,
|
|
255
|
-
default="0.95",
|
|
256
|
-
validators=[MinValueValidator(0.01), MaxValueValidator(1.00)],
|
|
257
|
+
default=Decimal("0.95"),
|
|
258
|
+
validators=[MinValueValidator(Decimal("0.01")), MaxValueValidator(Decimal("1.00"))],
|
|
257
259
|
help_text="Power factor (0.01-1.00) for converting between watts (W) and volt-amps (VA). Defaults to 0.95.",
|
|
258
260
|
)
|
|
259
261
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
1
2
|
import re
|
|
2
3
|
|
|
3
4
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
|
@@ -402,8 +403,8 @@ class PowerPort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
|
402
403
|
power_factor = models.DecimalField(
|
|
403
404
|
max_digits=4,
|
|
404
405
|
decimal_places=2,
|
|
405
|
-
default="0.95",
|
|
406
|
-
validators=[MinValueValidator(0.01), MaxValueValidator(1.00)],
|
|
406
|
+
default=Decimal("0.95"),
|
|
407
|
+
validators=[MinValueValidator(Decimal("0.01")), MaxValueValidator(Decimal("1.00"))],
|
|
407
408
|
help_text="Power factor (0.01-1.00) for converting between watts (W) and volt-amps (VA). Defaults to 0.95.",
|
|
408
409
|
)
|
|
409
410
|
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -940,6 +940,10 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
940
940
|
"""
|
|
941
941
|
return self.virtual_chassis.master if self.virtual_chassis else None
|
|
942
942
|
|
|
943
|
+
@property
|
|
944
|
+
def is_vc_master(self):
|
|
945
|
+
return self == self.get_vc_master()
|
|
946
|
+
|
|
943
947
|
@property
|
|
944
948
|
def vc_interfaces(self):
|
|
945
949
|
"""
|
nautobot/dcim/tables/__init__.py
CHANGED
|
@@ -39,6 +39,7 @@ from .devices import (
|
|
|
39
39
|
RearPortTable,
|
|
40
40
|
SoftwareImageFileTable,
|
|
41
41
|
SoftwareVersionTable,
|
|
42
|
+
VirtualChassisMembersTable,
|
|
42
43
|
VirtualChassisTable,
|
|
43
44
|
VirtualDeviceContextTable,
|
|
44
45
|
)
|
|
@@ -125,6 +126,7 @@ __all__ = (
|
|
|
125
126
|
"RearPortTemplateTable",
|
|
126
127
|
"SoftwareImageFileTable",
|
|
127
128
|
"SoftwareVersionTable",
|
|
129
|
+
"VirtualChassisMembersTable",
|
|
128
130
|
"VirtualChassisTable",
|
|
129
131
|
"VirtualDeviceContextTable",
|
|
130
132
|
)
|
nautobot/dcim/tables/devices.py
CHANGED
|
@@ -154,6 +154,30 @@ class PlatformTable(BaseTable):
|
|
|
154
154
|
#
|
|
155
155
|
|
|
156
156
|
|
|
157
|
+
class VirtualChassisMembersTable(BaseTable):
|
|
158
|
+
name = tables.TemplateColumn(order_by=("_name",), template_code=DEVICE_LINK, verbose_name="Device")
|
|
159
|
+
vc_position = tables.TemplateColumn(
|
|
160
|
+
verbose_name="Position", template_code='<span class="badge badge-default">{{ record.vc_position }}</span>'
|
|
161
|
+
)
|
|
162
|
+
master = BooleanColumn(accessor="is_vc_master", verbose_name="Master")
|
|
163
|
+
vc_priority = tables.Column(verbose_name="Priority")
|
|
164
|
+
|
|
165
|
+
class Meta(BaseTable.Meta):
|
|
166
|
+
model = Device
|
|
167
|
+
fields = (
|
|
168
|
+
"name",
|
|
169
|
+
"vc_position",
|
|
170
|
+
"master",
|
|
171
|
+
"vc_priority",
|
|
172
|
+
)
|
|
173
|
+
default_columns = (
|
|
174
|
+
"name",
|
|
175
|
+
"vc_position",
|
|
176
|
+
"master",
|
|
177
|
+
"vc_priority",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
157
181
|
class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
158
182
|
pk = ToggleColumn()
|
|
159
183
|
name = tables.TemplateColumn(order_by=("_name",), template_code=DEVICE_LINK)
|
nautobot/dcim/tables/power.py
CHANGED
|
@@ -76,8 +76,8 @@ class PowerFeedTable(StatusTableMixin, CableTerminationTable):
|
|
|
76
76
|
rack = tables.Column(linkify=True)
|
|
77
77
|
type = ChoiceFieldColumn()
|
|
78
78
|
power_path = tables.Column()
|
|
79
|
-
occupied_positions = tables.Column(accessor="occupied_positions", verbose_name="Position")
|
|
80
|
-
phase_designation = tables.Column(accessor="phase_designation", verbose_name="Phase Designation")
|
|
79
|
+
occupied_positions = tables.Column(accessor="occupied_positions", verbose_name="Position", orderable=False)
|
|
80
|
+
phase_designation = tables.Column(accessor="phase_designation", verbose_name="Phase Designation", orderable=False)
|
|
81
81
|
max_utilization = tables.TemplateColumn(template_code="{{ value }}%")
|
|
82
82
|
available_power = tables.Column(verbose_name="Available power (VA)")
|
|
83
83
|
tags = TagColumn(url_name="dcim:powerfeed_list")
|
|
@@ -2,20 +2,10 @@
|
|
|
2
2
|
{% load helpers %}
|
|
3
3
|
{% load static %}
|
|
4
4
|
|
|
5
|
-
{% block breadcrumbs %}
|
|
6
|
-
<li><a href="{% url 'dcim:device_list' %}">Devices</a></li>
|
|
7
|
-
<li><a href="{% url 'dcim:device_list' %}?location={{ object.location.pk }}">{{ object.location }}</a></li>
|
|
8
|
-
{% if object.parent_bay %}
|
|
9
|
-
<li>{{ object.parent_bay.device|hyperlinked_object }}</li>
|
|
10
|
-
<li>{{ object.parent_bay }}</li>
|
|
11
|
-
{% endif %}
|
|
12
|
-
<li>{{ object|hyperlinked_object }}</li>
|
|
13
|
-
{% endblock breadcrumbs %}
|
|
14
|
-
|
|
15
5
|
{% block masthead %}
|
|
16
6
|
<span class="hover_copy">
|
|
17
7
|
<h1>
|
|
18
|
-
<span id="devicename">{% block title %}{{
|
|
8
|
+
<span id="devicename">{% block title %}{{ block.super }}{% endblock title %}</span>
|
|
19
9
|
<button class="btn btn-xs btn-default hover_copy_button" data-clipboard-text="{{ object }}">
|
|
20
10
|
<span class="mdi mdi-content-copy"></span>
|
|
21
11
|
</button>
|