nautobot 2.4.14__py3-none-any.whl → 2.4.16__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.
- nautobot/apps/choices.py +8 -0
- nautobot/apps/ui.py +14 -0
- nautobot/core/api/views.py +2 -0
- nautobot/core/choices.py +4 -0
- nautobot/core/filters.py +21 -41
- nautobot/core/management/commands/check_job_approval_status.py +47 -0
- nautobot/core/management/commands/generate_test_data.py +1 -1
- nautobot/core/management/commands/migrate.py +1 -1
- nautobot/core/models/tree_queries.py +17 -0
- nautobot/core/settings.py +2 -2
- nautobot/core/tables.py +25 -2
- nautobot/core/templates/base_django.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/generic/object_list.html +17 -20
- nautobot/core/templates/inc/breadcrumbs.html +14 -0
- nautobot/core/templatetags/buttons.py +2 -4
- nautobot/core/templatetags/helpers.py +29 -6
- nautobot/core/templatetags/ui_framework.py +21 -0
- nautobot/core/testing/filters.py +20 -3
- nautobot/core/testing/forms.py +1 -1
- nautobot/core/tests/integration/test_filters.py +2 -2
- nautobot/core/tests/test_breadcrumbs.py +366 -0
- nautobot/core/tests/test_commands.py +40 -0
- nautobot/core/tests/test_filters.py +51 -1
- nautobot/core/tests/test_forms.py +1 -1
- nautobot/core/tests/test_graphql.py +4 -4
- nautobot/core/tests/test_titles.py +183 -0
- nautobot/core/tests/test_tree_queries.py +30 -0
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/tests/test_views_utils.py +1 -1
- nautobot/core/ui/breadcrumbs.py +538 -0
- nautobot/core/ui/bulk_buttons.py +53 -0
- nautobot/core/ui/object_detail.py +31 -8
- nautobot/core/ui/titles.py +127 -0
- nautobot/core/ui/utils.py +25 -0
- nautobot/core/utils/migrations.py +1 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/mixins.py +26 -1
- nautobot/core/views/renderers.py +20 -2
- nautobot/core/views/utils.py +13 -12
- nautobot/dcim/api/serializers.py +9 -0
- nautobot/dcim/choices.py +53 -0
- nautobot/dcim/filters/__init__.py +15 -3
- nautobot/dcim/forms.py +120 -7
- nautobot/dcim/management/commands/trace_paths.py +1 -1
- nautobot/dcim/migrations/0072_alter_powerfeed_options_and_more.py +97 -0
- nautobot/dcim/models/device_component_templates.py +8 -0
- nautobot/dcim/models/device_components.py +31 -12
- nautobot/dcim/models/devices.py +1 -1
- nautobot/dcim/models/power.py +171 -10
- nautobot/dcim/models/racks.py +7 -4
- nautobot/dcim/tables/devices.py +2 -0
- nautobot/dcim/tables/devicetypes.py +1 -0
- nautobot/dcim/tables/power.py +30 -2
- nautobot/dcim/templates/dcim/device.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -214
- nautobot/dcim/templates/dcim/location_retrieve.html +2 -2
- nautobot/dcim/templates/dcim/powerfeed_edit.html +8 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -1
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +61 -0
- nautobot/dcim/tests/test_api.py +24 -4
- nautobot/dcim/tests/test_filters.py +91 -13
- nautobot/dcim/tests/test_models.py +262 -0
- nautobot/dcim/tests/test_views.py +20 -12
- nautobot/dcim/utils.py +9 -0
- nautobot/dcim/views.py +390 -77
- nautobot/extras/factory.py +19 -20
- nautobot/extras/filters/__init__.py +3 -2
- nautobot/extras/filters/mixins.py +15 -1
- nautobot/extras/forms/__init__.py +2 -1
- nautobot/extras/forms/forms.py +62 -0
- nautobot/extras/managers.py +4 -1
- nautobot/extras/migrations/0125_jobresult_date_started.py +18 -0
- nautobot/extras/models/customfields.py +1 -2
- nautobot/extras/models/datasources.py +1 -2
- nautobot/extras/models/jobs.py +7 -3
- nautobot/extras/plugins/views.py +24 -1
- nautobot/extras/secrets/__init__.py +1 -1
- nautobot/extras/tables.py +21 -0
- nautobot/extras/templates/extras/customfield.html +2 -129
- nautobot/extras/templates/extras/customfield_edit.html +2 -108
- nautobot/extras/templates/extras/customfield_retrieve.html +129 -0
- nautobot/extras/templates/extras/customfield_update.html +108 -0
- nautobot/extras/templates/extras/inc/jobresult.html +7 -3
- nautobot/extras/templates/extras/jobresult.html +2 -155
- nautobot/extras/templates/extras/jobresult_retrieve.html +155 -0
- nautobot/extras/templates/extras/marketplace.html +5 -6
- nautobot/extras/templates/extras/note.html +2 -53
- nautobot/extras/templates/extras/note_retrieve.html +53 -0
- nautobot/extras/templates/extras/plugins_list.html +5 -6
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +2 -29
- nautobot/extras/templatetags/custom_links.py +2 -2
- nautobot/extras/templatetags/job_buttons.py +1 -1
- nautobot/extras/templatetags/plugins.py +1 -1
- nautobot/extras/tests/integration/test_computedfields.py +2 -2
- nautobot/extras/tests/integration/test_customfields.py +14 -11
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_notes.py +1 -1
- nautobot/extras/tests/integration/test_plugins.py +6 -6
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_filters.py +9 -0
- nautobot/extras/tests/test_forms.py +2 -2
- nautobot/extras/tests/test_plugins.py +14 -3
- nautobot/extras/tests/test_relationships.py +7 -7
- nautobot/extras/tests/test_views.py +172 -1
- nautobot/extras/urls.py +3 -59
- nautobot/extras/utils.py +1 -1
- nautobot/extras/views.py +96 -182
- nautobot/ipam/tables.py +8 -15
- nautobot/ipam/tests/migration/test_migrations.py +8 -8
- nautobot/ipam/tests/test_api.py +2 -2
- nautobot/ipam/tests/test_models.py +1 -1
- nautobot/project-static/docs/404.html +23 -0
- nautobot/project-static/docs/apps/index.html +23 -0
- nautobot/project-static/docs/apps/nautobot-apps.html +23 -0
- nautobot/project-static/docs/assets/_mkdocstrings.css +44 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +28 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +25 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +128 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +37 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +39 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +25 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +24 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +32 -5
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +41 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +39 -7
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +43 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +74 -59
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +143 -28
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +43 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +135 -53
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +229 -36
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +27 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +30 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +162 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +258 -51
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5987 -2620
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +25 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +154 -55
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +150 -35
- nautobot/project-static/docs/development/apps/api/configuration-view.html +23 -0
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/global-search.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/graphql.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +23 -0
- nautobot/project-static/docs/development/apps/api/prometheus.html +23 -0
- nautobot/project-static/docs/development/apps/api/setup.html +23 -0
- nautobot/project-static/docs/development/apps/api/testing.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/base-template.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +31 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/notes.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/urls.html +23 -0
- nautobot/project-static/docs/development/apps/index.html +23 -0
- nautobot/project-static/docs/development/apps/migration/code-updates.html +23 -0
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +23 -0
- nautobot/project-static/docs/development/apps/migration/from-v1.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +23 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +26 -3
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +10544 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +23 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +23 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +23 -0
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +26 -3
- nautobot/project-static/docs/development/core/application-registry.html +23 -0
- nautobot/project-static/docs/development/core/best-practices.html +23 -0
- nautobot/project-static/docs/development/core/bootstrap-ui.html +23 -0
- nautobot/project-static/docs/development/core/caching.html +23 -0
- nautobot/project-static/docs/development/core/controllers.html +23 -0
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +23 -0
- nautobot/project-static/docs/development/core/generic-views.html +23 -0
- nautobot/project-static/docs/development/core/getting-started.html +23 -0
- nautobot/project-static/docs/development/core/homepage.html +23 -0
- nautobot/project-static/docs/development/core/index.html +23 -0
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +23 -0
- nautobot/project-static/docs/development/core/model-checklist.html +23 -0
- nautobot/project-static/docs/development/core/model-features.html +23 -0
- nautobot/project-static/docs/development/core/natural-keys.html +23 -0
- nautobot/project-static/docs/development/core/navigation-menu.html +23 -0
- nautobot/project-static/docs/development/core/release-checklist.html +23 -0
- nautobot/project-static/docs/development/core/role-internals.html +23 -0
- nautobot/project-static/docs/development/core/settings.html +23 -0
- nautobot/project-static/docs/development/core/style-guide.html +23 -0
- nautobot/project-static/docs/development/core/templates.html +23 -0
- nautobot/project-static/docs/development/core/testing.html +23 -0
- nautobot/project-static/docs/development/core/ui-component-framework.html +713 -255
- nautobot/project-static/docs/development/core/user-preferences.html +23 -0
- nautobot/project-static/docs/development/index.html +23 -0
- nautobot/project-static/docs/development/jobs/getting-started.html +23 -0
- nautobot/project-static/docs/development/jobs/index.html +23 -0
- nautobot/project-static/docs/development/jobs/installation.html +23 -0
- nautobot/project-static/docs/development/jobs/job-extensions.html +23 -0
- nautobot/project-static/docs/development/jobs/job-logging.html +23 -0
- nautobot/project-static/docs/development/jobs/job-patterns.html +23 -0
- nautobot/project-static/docs/development/jobs/job-structure.html +23 -0
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +23 -0
- nautobot/project-static/docs/development/jobs/testing.html +23 -0
- nautobot/project-static/docs/index.html +23 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/breadcrumbs-titles-data-flow.png +0 -0
- nautobot/project-static/docs/media/power_distribution.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +23 -0
- nautobot/project-static/docs/overview/design_philosophy.html +23 -0
- nautobot/project-static/docs/release-notes/index.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.0.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.1.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.2.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.3.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.4.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.5.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.6.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.0.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.1.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.2.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.3.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.4.html +306 -0
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/services.html +23 -0
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +23 -0
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +23 -0
- nautobot/project-static/docs/user-guide/administration/security/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/security/notices.html +23 -0
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +284 -219
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +305 -5
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +24 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +136 -3
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +41 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +40 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +23 -0
- nautobot/project-static/docs/user-guide/index.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +24 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +23 -0
- nautobot/users/tests/test_api.py +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -252
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -75
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +252 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +75 -0
- nautobot/virtualization/urls.py +3 -61
- nautobot/virtualization/views.py +48 -72
- {nautobot-2.4.14.dist-info → nautobot-2.4.16.dist-info}/METADATA +24 -24
- {nautobot-2.4.14.dist-info → nautobot-2.4.16.dist-info}/RECORD +434 -417
- {nautobot-2.4.14.dist-info → nautobot-2.4.16.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.14.dist-info → nautobot-2.4.16.dist-info}/NOTICE +0 -0
- {nautobot-2.4.14.dist-info → nautobot-2.4.16.dist-info}/WHEEL +0 -0
- {nautobot-2.4.14.dist-info → nautobot-2.4.16.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from typing import Literal, Optional
|
|
2
|
+
|
|
3
|
+
from django.template import Context, Template
|
|
4
|
+
from django.utils.html import strip_tags
|
|
5
|
+
|
|
6
|
+
DEFAULT_TITLES: dict[str, str] = {
|
|
7
|
+
"list": "{{ verbose_name_plural|bettertitle }}",
|
|
8
|
+
"detail": "{{ object.display|default:object }}",
|
|
9
|
+
"retrieve": "{{ object.display|default:object }}",
|
|
10
|
+
"destroy": "Delete {{ verbose_name }}?",
|
|
11
|
+
"create": "Add a new {{ verbose_name }}",
|
|
12
|
+
"update": "Editing {{ verbose_name }} {{ object.display|default:object }}",
|
|
13
|
+
"bulk_destroy": "Delete {{ total_objs_to_delete }} {{ verbose_name_plural|bettertitle }}?",
|
|
14
|
+
"bulk_rename": "Renaming {{ selected_objects|length }} {{ verbose_name_plural|bettertitle }} on {{ parent_name }}",
|
|
15
|
+
"bulk_update": "Editing {{ objs_count }} {{ verbose_name_plural|bettertitle }}",
|
|
16
|
+
"changelog": "{{ object.display|default:object }} - Change Log",
|
|
17
|
+
"notes": "{{ object.display|default:object }} - Notes",
|
|
18
|
+
"approve": "Approve {{ verbose_name|bettertitle }}?",
|
|
19
|
+
"deny": "Deny {{ verbose_name|bettertitle }}?",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
DEFAULT_PLUGINS = ["helpers"]
|
|
23
|
+
|
|
24
|
+
ModeType = Literal["html", "plain"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Titles:
|
|
28
|
+
"""
|
|
29
|
+
Base class for document titles and page headings.
|
|
30
|
+
|
|
31
|
+
This class provides a mechanism to define per-action title templates.
|
|
32
|
+
Titles can be dynamically rendered using context variables and template tags using the Django template engine and context.
|
|
33
|
+
Use the `render()` method to obtain either rich (HTML) or plain (stripped of HTML) output.
|
|
34
|
+
|
|
35
|
+
There is a dedicated simple tag to render `Titles` passed in the `context['view_titles']`: `{% render_title mode="html" %}`
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
titles (dict[str, str]): Action-to-title-template mapping.
|
|
39
|
+
template_plugins (list[str]): List of Django template libraries to load before rendering.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
template_plugins (Optional[list[str]]): Template libraries to load into rendering.
|
|
43
|
+
titles (dict): Action-to-template-string mappings that override or extend the defaults.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, template_plugins: Optional[list[str]] = None, titles: Optional[dict[str, str]] = None):
|
|
47
|
+
"""
|
|
48
|
+
Keyword arguments passed can either add new action-title pair or override existing titles.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
template_plugins (Optional[list[str]]): Extra Django template libraries to load before rendering.
|
|
52
|
+
titles (Optional[dict[str, str]]): Custom or overriding mappings from action to template string.
|
|
53
|
+
"""
|
|
54
|
+
self.titles: dict[str, str] = DEFAULT_TITLES.copy()
|
|
55
|
+
if titles:
|
|
56
|
+
self.titles.update(**titles)
|
|
57
|
+
|
|
58
|
+
self.template_plugins: list[str] = DEFAULT_PLUGINS.copy()
|
|
59
|
+
if template_plugins:
|
|
60
|
+
self.template_plugins.extend(template_plugins)
|
|
61
|
+
|
|
62
|
+
def render(self, context: Context, mode: ModeType = "html") -> str:
|
|
63
|
+
"""
|
|
64
|
+
Renders the title based on given context and current action.
|
|
65
|
+
|
|
66
|
+
If mode == "plain", the output will be stripped of HTML tags.
|
|
67
|
+
|
|
68
|
+
Make sure that needed context variables are in context and needed plugins are loaded.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
context (Context): Render context.
|
|
72
|
+
mode (ModeType): Rendering mode: "html" or "plain".
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
(str): HTML fragment or plain text, depending on `mode`.
|
|
76
|
+
"""
|
|
77
|
+
with context.update(self.get_extra_context(context)):
|
|
78
|
+
template_str = self.get_template_str(context)
|
|
79
|
+
template = Template(self.template_plugins_str + template_str)
|
|
80
|
+
rendered_title = template.render(context)
|
|
81
|
+
if mode == "plain":
|
|
82
|
+
return strip_tags(rendered_title)
|
|
83
|
+
return rendered_title
|
|
84
|
+
|
|
85
|
+
def get_template_str(self, context: Context) -> str:
|
|
86
|
+
"""
|
|
87
|
+
Determine the template string for the current action.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
context (Context): Render context.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
str: The template string for the current action, or an empty string if not found.
|
|
94
|
+
"""
|
|
95
|
+
action = context.get("view_action", "list")
|
|
96
|
+
|
|
97
|
+
template_str = self.titles.get(action)
|
|
98
|
+
if template_str:
|
|
99
|
+
return template_str
|
|
100
|
+
|
|
101
|
+
detail = context.get("detail", False)
|
|
102
|
+
if detail:
|
|
103
|
+
return self.titles.get("detail", "")
|
|
104
|
+
|
|
105
|
+
return ""
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def template_plugins_str(self) -> str:
|
|
109
|
+
"""
|
|
110
|
+
Return a concatenated string of Django {% load ... %} tags for all template plugins.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
str: String containing {% load ... %} tags for the required template libraries.
|
|
114
|
+
"""
|
|
115
|
+
return "".join(f"{{% load {plugin_name} %}}" for plugin_name in self.template_plugins)
|
|
116
|
+
|
|
117
|
+
def get_extra_context(self, context: Context) -> dict:
|
|
118
|
+
"""
|
|
119
|
+
Provide additional data to include in the rendering context, based on the configuration of this component.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
context (Context): The current template context.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
(dict): Additional context data.
|
|
126
|
+
"""
|
|
127
|
+
return {}
|
nautobot/core/ui/utils.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from django.db.models import Model
|
|
1
4
|
from django.template import Context
|
|
2
5
|
from django.template.loader import get_template
|
|
3
6
|
|
|
@@ -34,3 +37,25 @@ def render_component_template(template_path: str, context: Context, **kwargs) ->
|
|
|
34
37
|
"""
|
|
35
38
|
with context.update(kwargs):
|
|
36
39
|
return get_template(template_path).render(flatten_context(context))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_absolute_url(value: Optional[Model]) -> str:
|
|
43
|
+
"""
|
|
44
|
+
Function to retrieve just absolute url to the given model instance.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
value (Optional[django.db.models.Model]): Instance of a Django model or None.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
(str): url to the object if it defines get_absolute_url(), empty string otherwise.
|
|
51
|
+
"""
|
|
52
|
+
if value is None:
|
|
53
|
+
return ""
|
|
54
|
+
|
|
55
|
+
if hasattr(value, "get_absolute_url"):
|
|
56
|
+
try:
|
|
57
|
+
return value.get_absolute_url()
|
|
58
|
+
except AttributeError:
|
|
59
|
+
return ""
|
|
60
|
+
|
|
61
|
+
return ""
|
|
@@ -21,7 +21,7 @@ def check_for_duplicates_with_natural_key_fields_in_migration(model_class, natur
|
|
|
21
21
|
if duplicate_records.exists():
|
|
22
22
|
if len(natural_key_fields) > 1:
|
|
23
23
|
print(
|
|
24
|
-
f" Duplicate {model_class.__name__} attributes '{*natural_key_fields,}' detected: {list(duplicate_records.values_list(*natural_key_fields))}",
|
|
24
|
+
f" Duplicate {model_class.__name__} attributes '{(*natural_key_fields,)}' detected: {list(duplicate_records.values_list(*natural_key_fields))}",
|
|
25
25
|
file=sys.stderr,
|
|
26
26
|
)
|
|
27
27
|
else:
|
nautobot/core/views/__init__.py
CHANGED
|
@@ -70,7 +70,7 @@ class HomeView(AccessMixin, TemplateView):
|
|
|
70
70
|
context[key] = data
|
|
71
71
|
|
|
72
72
|
# Create standalone template
|
|
73
|
-
path = f
|
|
73
|
+
path = f"{details['template_path']}{details['custom_template']}"
|
|
74
74
|
if os.path.isfile(path):
|
|
75
75
|
with open(path, "r") as f:
|
|
76
76
|
html = f.read()
|
nautobot/core/views/mixins.py
CHANGED
|
@@ -41,6 +41,8 @@ from nautobot.core.forms import (
|
|
|
41
41
|
restrict_form_fields,
|
|
42
42
|
)
|
|
43
43
|
from nautobot.core.jobs import BulkDeleteObjects, BulkEditObjects
|
|
44
|
+
from nautobot.core.ui.breadcrumbs import Breadcrumbs
|
|
45
|
+
from nautobot.core.ui.titles import Titles
|
|
44
46
|
from nautobot.core.utils import filtering, lookup, permissions
|
|
45
47
|
from nautobot.core.utils.requests import get_filterable_params_from_filter_params, normalize_querydict
|
|
46
48
|
from nautobot.core.views.renderers import NautobotHTMLRenderer
|
|
@@ -242,6 +244,22 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
|
|
|
242
244
|
# custom view attributes used for permission checks and handling
|
|
243
245
|
custom_view_base_action = None
|
|
244
246
|
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
|
+
|
|
256
|
+
@staticmethod
|
|
257
|
+
def instantiate_if_needed(attr, default_cls):
|
|
258
|
+
if attr is None:
|
|
259
|
+
return default_cls()
|
|
260
|
+
if isinstance(attr, type):
|
|
261
|
+
return attr()
|
|
262
|
+
return attr
|
|
245
263
|
|
|
246
264
|
def get_permissions_for_model(self, model, actions):
|
|
247
265
|
"""
|
|
@@ -868,7 +886,7 @@ class ObjectEditViewMixin(NautobotViewSetMixin, mixins.CreateModelMixin, mixins.
|
|
|
868
886
|
if hasattr(form, "save_note") and callable(form.save_note):
|
|
869
887
|
form.save_note(instance=obj, user=request.user)
|
|
870
888
|
|
|
871
|
-
msg = f'
|
|
889
|
+
msg = f"{'Created' if object_created else 'Modified'} {queryset.model._meta.verbose_name}"
|
|
872
890
|
self.logger.info(f"{msg} {obj} (PK: {obj.pk})")
|
|
873
891
|
try:
|
|
874
892
|
msg = format_html(
|
|
@@ -1142,6 +1160,9 @@ class ObjectBulkDestroyViewMixin(NautobotViewSetMixin, BulkDestroyModelMixin, Bu
|
|
|
1142
1160
|
f"No {queryset.model._meta.verbose_name_plural} were selected for deletion.",
|
|
1143
1161
|
)
|
|
1144
1162
|
return redirect(self.get_return_url(request))
|
|
1163
|
+
# Hide actions column in the table for bulk destroy view
|
|
1164
|
+
if "actions" in table.columns:
|
|
1165
|
+
table.columns.hide("actions")
|
|
1145
1166
|
|
|
1146
1167
|
data.update(
|
|
1147
1168
|
{
|
|
@@ -1338,6 +1359,10 @@ class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin, Bulk
|
|
|
1338
1359
|
f"No {queryset.model._meta.verbose_name_plural} were selected to update.",
|
|
1339
1360
|
)
|
|
1340
1361
|
return redirect(self.get_return_url(request))
|
|
1362
|
+
|
|
1363
|
+
# Hide actions column in the table for bulk update view
|
|
1364
|
+
if "actions" in table.columns:
|
|
1365
|
+
table.columns.hide("actions")
|
|
1341
1366
|
data.update(
|
|
1342
1367
|
{
|
|
1343
1368
|
"table": table,
|
nautobot/core/views/renderers.py
CHANGED
|
@@ -228,7 +228,7 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
|
|
|
228
228
|
if view.filterset is not None:
|
|
229
229
|
filterset_filters = view.filterset.filters
|
|
230
230
|
else:
|
|
231
|
-
filterset_filters = view.
|
|
231
|
+
filterset_filters = view.filterset_class.get_filters()
|
|
232
232
|
display_filter_params = [
|
|
233
233
|
check_filter_for_display(filterset_filters, field_name, values)
|
|
234
234
|
for field_name, values in view.filter_params.items()
|
|
@@ -279,6 +279,7 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
|
|
|
279
279
|
|
|
280
280
|
context = {
|
|
281
281
|
"content_type": content_type,
|
|
282
|
+
"model": model,
|
|
282
283
|
"form": form,
|
|
283
284
|
"filter_form": filter_form,
|
|
284
285
|
"dynamic_filter_form": self.get_dynamic_filter_form(view, request, filterset_class=view.filterset_class),
|
|
@@ -294,7 +295,13 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
|
|
|
294
295
|
"table_config_form": TableConfigForm(table=table) if table else None,
|
|
295
296
|
"verbose_name": queryset.model._meta.verbose_name,
|
|
296
297
|
"verbose_name_plural": queryset.model._meta.verbose_name_plural,
|
|
298
|
+
"view_action": view.action,
|
|
299
|
+
"detail": False,
|
|
297
300
|
}
|
|
301
|
+
|
|
302
|
+
self._set_context_from_method(view, "get_view_titles", context, "view_titles")
|
|
303
|
+
self._set_context_from_method(view, "get_breadcrumbs", context, "breadcrumbs")
|
|
304
|
+
|
|
298
305
|
if view.detail:
|
|
299
306
|
# If we are in a retrieve related detail view (retrieve and custom actions).
|
|
300
307
|
try:
|
|
@@ -316,7 +323,6 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
|
|
|
316
323
|
new_changes_not_applied = view_changes_not_saved(request, view, self.saved_view)
|
|
317
324
|
context.update(
|
|
318
325
|
{
|
|
319
|
-
"model": model,
|
|
320
326
|
"current_saved_view": self.saved_view,
|
|
321
327
|
"new_changes_not_applied": new_changes_not_applied,
|
|
322
328
|
"action_buttons": valid_actions,
|
|
@@ -364,3 +370,15 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
|
|
|
364
370
|
self.template = data.get("template", view.get_template_name())
|
|
365
371
|
|
|
366
372
|
return super().render(data, accepted_media_type=accepted_media_type, renderer_context=renderer_context)
|
|
373
|
+
|
|
374
|
+
@staticmethod
|
|
375
|
+
def _set_context_from_method(
|
|
376
|
+
view,
|
|
377
|
+
view_function,
|
|
378
|
+
context,
|
|
379
|
+
context_key,
|
|
380
|
+
):
|
|
381
|
+
try:
|
|
382
|
+
context[context_key] = getattr(view, view_function)()
|
|
383
|
+
except AttributeError:
|
|
384
|
+
context[context_key] = None
|
nautobot/core/views/utils.py
CHANGED
|
@@ -134,13 +134,13 @@ def get_csv_form_fields_from_serializer_class(serializer_class):
|
|
|
134
134
|
"help_text": cf_form_field.help_text,
|
|
135
135
|
}
|
|
136
136
|
if cf.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
|
|
137
|
-
field_info["format"] = mark_safe("<code>true</code> or <code>false</code>")
|
|
137
|
+
field_info["format"] = mark_safe("<code>true</code> or <code>false</code>")
|
|
138
138
|
elif cf.type == CustomFieldTypeChoices.TYPE_DATE:
|
|
139
|
-
field_info["format"] = mark_safe("<code>YYYY-MM-DD</code>")
|
|
139
|
+
field_info["format"] = mark_safe("<code>YYYY-MM-DD</code>")
|
|
140
140
|
elif cf.type == CustomFieldTypeChoices.TYPE_SELECT:
|
|
141
141
|
field_info["choices"] = {value: value for value in cf.choices}
|
|
142
142
|
elif cf.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
|
|
143
|
-
field_info["format"] = mark_safe('<code>"value,value"</code>')
|
|
143
|
+
field_info["format"] = mark_safe('<code>"value,value"</code>')
|
|
144
144
|
field_info["choices"] = {value: value for value in cf.choices}
|
|
145
145
|
fields.append(field_info)
|
|
146
146
|
continue
|
|
@@ -153,29 +153,29 @@ def get_csv_form_fields_from_serializer_class(serializer_class):
|
|
|
153
153
|
"help_text": field.help_text,
|
|
154
154
|
}
|
|
155
155
|
if isinstance(field, serializers.BooleanField):
|
|
156
|
-
field_info["format"] = mark_safe("<code>true</code> or <code>false</code>")
|
|
156
|
+
field_info["format"] = mark_safe("<code>true</code> or <code>false</code>")
|
|
157
157
|
elif isinstance(field, serializers.DateField):
|
|
158
|
-
field_info["format"] = mark_safe("<code>YYYY-MM-DD</code>")
|
|
158
|
+
field_info["format"] = mark_safe("<code>YYYY-MM-DD</code>")
|
|
159
159
|
elif isinstance(field, TimeZoneSerializerField):
|
|
160
|
-
field_info["format"] = mark_safe(
|
|
160
|
+
field_info["format"] = mark_safe(
|
|
161
161
|
'<a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">available options</a>'
|
|
162
162
|
)
|
|
163
163
|
elif isinstance(field, serializers.ManyRelatedField):
|
|
164
164
|
if field.field_name == "tags":
|
|
165
|
-
field_info["format"] = mark_safe('<code>"name,name"</code> or <code>"UUID,UUID"</code>')
|
|
165
|
+
field_info["format"] = mark_safe('<code>"name,name"</code> or <code>"UUID,UUID"</code>')
|
|
166
166
|
elif isinstance(field.child_relation, ContentTypeField):
|
|
167
|
-
field_info["format"] = mark_safe('<code>"app_label.model,app_label.model"</code>')
|
|
167
|
+
field_info["format"] = mark_safe('<code>"app_label.model,app_label.model"</code>')
|
|
168
168
|
else:
|
|
169
169
|
field_info["foreign_key"] = field.child_relation.queryset.model._meta.label_lower
|
|
170
|
-
field_info["format"] = mark_safe('<code>"UUID,UUID"</code> or combination of fields')
|
|
170
|
+
field_info["format"] = mark_safe('<code>"UUID,UUID"</code> or combination of fields')
|
|
171
171
|
elif isinstance(field, serializers.RelatedField):
|
|
172
172
|
if isinstance(field, ContentTypeField):
|
|
173
|
-
field_info["format"] = mark_safe("<code>app_label.model</code>")
|
|
173
|
+
field_info["format"] = mark_safe("<code>app_label.model</code>")
|
|
174
174
|
else:
|
|
175
175
|
field_info["foreign_key"] = field.queryset.model._meta.label_lower
|
|
176
|
-
field_info["format"] = mark_safe("<code>UUID</code> or combination of fields")
|
|
176
|
+
field_info["format"] = mark_safe("<code>UUID</code> or combination of fields")
|
|
177
177
|
elif isinstance(field, (serializers.ListField, serializers.MultipleChoiceField)):
|
|
178
|
-
field_info["format"] = mark_safe('<code>"value,value"</code>')
|
|
178
|
+
field_info["format"] = mark_safe('<code>"value,value"</code>')
|
|
179
179
|
elif isinstance(field, (serializers.DictField, serializers.JSONField)):
|
|
180
180
|
pass # Not trivial to specify a format as it could be a JSON dict or a comma-separated string
|
|
181
181
|
|
|
@@ -348,6 +348,7 @@ def common_detail_view_context(request, instance):
|
|
|
348
348
|
created_by, last_updated_by = get_created_and_last_updated_usernames_for_model(instance)
|
|
349
349
|
context["created_by"] = created_by
|
|
350
350
|
context["last_updated_by"] = last_updated_by
|
|
351
|
+
context["detail"] = True
|
|
351
352
|
|
|
352
353
|
if getattr(instance, "is_contact_associable_model", False):
|
|
353
354
|
paginate = {"paginator_class": EnhancedPaginator, "per_page": get_paginate_count(request)}
|
nautobot/dcim/api/serializers.py
CHANGED
|
@@ -35,11 +35,14 @@ from nautobot.dcim.choices import (
|
|
|
35
35
|
InterfaceRedundancyGroupProtocolChoices,
|
|
36
36
|
InterfaceTypeChoices,
|
|
37
37
|
PortTypeChoices,
|
|
38
|
+
PowerFeedBreakerPoleChoices,
|
|
38
39
|
PowerFeedPhaseChoices,
|
|
39
40
|
PowerFeedSupplyChoices,
|
|
40
41
|
PowerFeedTypeChoices,
|
|
41
42
|
PowerOutletFeedLegChoices,
|
|
42
43
|
PowerOutletTypeChoices,
|
|
44
|
+
PowerPanelTypeChoices,
|
|
45
|
+
PowerPathChoices,
|
|
43
46
|
PowerPortTypeChoices,
|
|
44
47
|
RackDimensionUnitChoices,
|
|
45
48
|
RackElevationDetailRenderChoices,
|
|
@@ -971,6 +974,8 @@ class VirtualChassisSerializer(TaggedModelSerializerMixin, NautobotModelSerializ
|
|
|
971
974
|
|
|
972
975
|
|
|
973
976
|
class PowerPanelSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
|
|
977
|
+
panel_type = ChoiceField(choices=PowerPanelTypeChoices, allow_blank=True, required=False)
|
|
978
|
+
power_path = ChoiceField(choices=PowerPathChoices, allow_blank=True, required=False)
|
|
974
979
|
power_feed_count = serializers.IntegerField(read_only=True)
|
|
975
980
|
|
|
976
981
|
class Meta:
|
|
@@ -985,8 +990,12 @@ class PowerFeedSerializer(
|
|
|
985
990
|
NautobotModelSerializer,
|
|
986
991
|
):
|
|
987
992
|
type = ChoiceField(choices=PowerFeedTypeChoices, default=PowerFeedTypeChoices.TYPE_PRIMARY)
|
|
993
|
+
power_path = ChoiceField(choices=PowerPathChoices, allow_blank=True, required=False)
|
|
988
994
|
supply = ChoiceField(choices=PowerFeedSupplyChoices, default=PowerFeedSupplyChoices.SUPPLY_AC)
|
|
989
995
|
phase = ChoiceField(choices=PowerFeedPhaseChoices, default=PowerFeedPhaseChoices.PHASE_SINGLE)
|
|
996
|
+
breaker_pole_count = ChoiceField(
|
|
997
|
+
choices=PowerFeedBreakerPoleChoices, allow_blank=True, allow_null=True, required=False
|
|
998
|
+
)
|
|
990
999
|
|
|
991
1000
|
class Meta:
|
|
992
1001
|
model = PowerFeed
|
nautobot/dcim/choices.py
CHANGED
|
@@ -1371,6 +1371,37 @@ class CableLengthUnitChoices(ChoiceSet):
|
|
|
1371
1371
|
)
|
|
1372
1372
|
|
|
1373
1373
|
|
|
1374
|
+
#
|
|
1375
|
+
# Power Panels
|
|
1376
|
+
#
|
|
1377
|
+
|
|
1378
|
+
|
|
1379
|
+
class PowerPanelTypeChoices(ChoiceSet):
|
|
1380
|
+
TYPE_UTILITY = "utility"
|
|
1381
|
+
TYPE_GENERATOR = "generator"
|
|
1382
|
+
TYPE_SWITCHGEAR = "switchgear"
|
|
1383
|
+
TYPE_MDP = "mdp"
|
|
1384
|
+
TYPE_UPS = "ups"
|
|
1385
|
+
TYPE_TRANSFER_SWITCH = "transfer-switch"
|
|
1386
|
+
TYPE_PDU = "pdu"
|
|
1387
|
+
TYPE_PANELBOARD = "panelboard"
|
|
1388
|
+
TYPE_MLC = "mlc"
|
|
1389
|
+
TYPE_RPP = "rpp"
|
|
1390
|
+
|
|
1391
|
+
CHOICES = (
|
|
1392
|
+
(TYPE_UTILITY, "Utility"),
|
|
1393
|
+
(TYPE_GENERATOR, "Generator"),
|
|
1394
|
+
(TYPE_SWITCHGEAR, "Switchgear"),
|
|
1395
|
+
(TYPE_MDP, "Main Distribution Panel (MDP)"),
|
|
1396
|
+
(TYPE_UPS, "Uninterruptible Power Supply (UPS)"),
|
|
1397
|
+
(TYPE_TRANSFER_SWITCH, "Transfer Switch (TS)"),
|
|
1398
|
+
(TYPE_PDU, "Power Distribution Unit (PDU)"),
|
|
1399
|
+
(TYPE_PANELBOARD, "Panelboard"),
|
|
1400
|
+
(TYPE_MLC, "Mini Load Center (MLC)"),
|
|
1401
|
+
(TYPE_RPP, "Remote Power Panel (RPP)"),
|
|
1402
|
+
)
|
|
1403
|
+
|
|
1404
|
+
|
|
1374
1405
|
#
|
|
1375
1406
|
# PowerFeeds
|
|
1376
1407
|
#
|
|
@@ -1405,6 +1436,16 @@ class PowerFeedTypeChoices(ChoiceSet):
|
|
|
1405
1436
|
}
|
|
1406
1437
|
|
|
1407
1438
|
|
|
1439
|
+
class PowerPathChoices(ChoiceSet):
|
|
1440
|
+
PATH_A = "a"
|
|
1441
|
+
PATH_B = "b"
|
|
1442
|
+
|
|
1443
|
+
CHOICES = (
|
|
1444
|
+
(PATH_A, "Path A"),
|
|
1445
|
+
(PATH_B, "Path B"),
|
|
1446
|
+
)
|
|
1447
|
+
|
|
1448
|
+
|
|
1408
1449
|
class PowerFeedSupplyChoices(ChoiceSet):
|
|
1409
1450
|
SUPPLY_AC = "ac"
|
|
1410
1451
|
SUPPLY_DC = "dc"
|
|
@@ -1425,6 +1466,18 @@ class PowerFeedPhaseChoices(ChoiceSet):
|
|
|
1425
1466
|
)
|
|
1426
1467
|
|
|
1427
1468
|
|
|
1469
|
+
class PowerFeedBreakerPoleChoices(ChoiceSet):
|
|
1470
|
+
POLE_1 = 1
|
|
1471
|
+
POLE_2 = 2
|
|
1472
|
+
POLE_3 = 3
|
|
1473
|
+
|
|
1474
|
+
CHOICES = [
|
|
1475
|
+
(POLE_1, "1-Pole"),
|
|
1476
|
+
(POLE_2, "2-Pole"),
|
|
1477
|
+
(POLE_3, "3-Pole"),
|
|
1478
|
+
]
|
|
1479
|
+
|
|
1480
|
+
|
|
1428
1481
|
#
|
|
1429
1482
|
# Device Redundancy Groups
|
|
1430
1483
|
#
|
|
@@ -1639,10 +1639,14 @@ class PowerPanelFilterSet(LocatableModelFilterSetMixin, NautobotFilterSet):
|
|
|
1639
1639
|
field_name="power_feeds",
|
|
1640
1640
|
label="Has power feeds",
|
|
1641
1641
|
)
|
|
1642
|
+
has_feeders = RelatedMembershipBooleanFilter(
|
|
1643
|
+
field_name="feeders",
|
|
1644
|
+
label="Has feeders",
|
|
1645
|
+
)
|
|
1642
1646
|
|
|
1643
1647
|
class Meta:
|
|
1644
1648
|
model = PowerPanel
|
|
1645
|
-
fields = ["id", "name", "tags"]
|
|
1649
|
+
fields = ["id", "name", "panel_type", "power_path", "tags"]
|
|
1646
1650
|
|
|
1647
1651
|
|
|
1648
1652
|
class PowerFeedFilterSet(
|
|
@@ -1652,8 +1656,7 @@ class PowerFeedFilterSet(
|
|
|
1652
1656
|
StatusModelFilterSetMixin,
|
|
1653
1657
|
):
|
|
1654
1658
|
q = SearchFilter(filter_predicates={"name": "icontains", "comments": "icontains"})
|
|
1655
|
-
|
|
1656
|
-
location = NaturalKeyOrPKMultipleChoiceFilter(
|
|
1659
|
+
location = TreeNodeMultipleChoiceFilter(
|
|
1657
1660
|
prefers_id=True,
|
|
1658
1661
|
field_name="power_panel__location",
|
|
1659
1662
|
queryset=Location.objects.all(),
|
|
@@ -1667,6 +1670,12 @@ class PowerFeedFilterSet(
|
|
|
1667
1670
|
to_field_name="name",
|
|
1668
1671
|
label="Power panel (name or ID)",
|
|
1669
1672
|
)
|
|
1673
|
+
destination_panel = NaturalKeyOrPKMultipleChoiceFilter(
|
|
1674
|
+
prefers_id=True,
|
|
1675
|
+
queryset=PowerPanel.objects.all(),
|
|
1676
|
+
to_field_name="name",
|
|
1677
|
+
label="Destination panel (name or ID)",
|
|
1678
|
+
)
|
|
1670
1679
|
# TODO: solve https://github.com/nautobot/nautobot/issues/2875 to use this filter correctly
|
|
1671
1680
|
rack = NaturalKeyOrPKMultipleChoiceFilter(
|
|
1672
1681
|
prefers_id=True,
|
|
@@ -1682,11 +1691,14 @@ class PowerFeedFilterSet(
|
|
|
1682
1691
|
"name",
|
|
1683
1692
|
"status",
|
|
1684
1693
|
"type",
|
|
1694
|
+
"power_path",
|
|
1685
1695
|
"supply",
|
|
1686
1696
|
"phase",
|
|
1687
1697
|
"voltage",
|
|
1688
1698
|
"amperage",
|
|
1689
1699
|
"max_utilization",
|
|
1700
|
+
"breaker_position",
|
|
1701
|
+
"breaker_pole_count",
|
|
1690
1702
|
"comments",
|
|
1691
1703
|
"available_power",
|
|
1692
1704
|
"tags",
|