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
|
@@ -1,21 +1,2 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
2
|
{% load helpers %}
|
|
3
|
-
|
|
4
|
-
{% block breadcrumbs %}
|
|
5
|
-
{% if object.device %}
|
|
6
|
-
<li><a href="{% url 'dcim:device_list' %}">Devices</a></li>
|
|
7
|
-
<li>{{ object.device|hyperlinked_object }}</li>
|
|
8
|
-
{% if device_breadcrumb_url %}
|
|
9
|
-
<li><a href="{% url device_breadcrumb_url pk=object.device.pk %}">{{ object|meta:"verbose_name_plural"|bettertitle }}</a></li>
|
|
10
|
-
{% endif %}
|
|
11
|
-
{% else %}
|
|
12
|
-
<li><a href="{% url 'dcim:module_list' %}">Modules</a></li>
|
|
13
|
-
<li>{{ object.module|hyperlinked_object }}</li>
|
|
14
|
-
{% if module_breadcrumb_url %}
|
|
15
|
-
<li><a href="{% url module_breadcrumb_url pk=object.module.pk %}">{{ object|meta:"verbose_name_plural"|bettertitle }}</a></li>
|
|
16
|
-
{% endif %}
|
|
17
|
-
{% endif %}
|
|
18
|
-
<li>{{ object|hyperlinked_object }}</li>
|
|
19
|
-
{% endblock breadcrumbs %}
|
|
20
|
-
|
|
21
|
-
{% block title %}{% if object.device %}{{ object.device }}{% else %}{{ object.module.display }}{% endif %} / {{ object }}{% endblock title %}
|
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
2
|
{% load helpers %}
|
|
3
|
-
{% block breadcrumbs %}
|
|
4
|
-
{% if object.parent_device %}
|
|
5
|
-
<li><a href="{% url 'dcim:device_list' %}">Devices</a></li>
|
|
6
|
-
<li>{{ object.parent_device|hyperlinked_object }}</li>
|
|
7
|
-
{% if device_breadcrumb_url %}
|
|
8
|
-
<li><a href="{% url device_breadcrumb_url pk=object.parent_device.pk %}">{{ object|meta:"verbose_name_plural"|bettertitle }}</a></li>
|
|
9
|
-
{% endif %}
|
|
10
|
-
{% else %}
|
|
11
|
-
<li><a href="{% url 'dcim:module_list' %}">Modules</a></li>
|
|
12
|
-
<li>{{ object.parent_module|hyperlinked_object }}</li>
|
|
13
|
-
{% if module_breadcrumb_url %}
|
|
14
|
-
<li><a href="{% url module_breadcrumb_url pk=object.parent_module.pk %}">{{ object|meta:"verbose_name_plural"|bettertitle }}</a></li>
|
|
15
|
-
{% endif %}
|
|
16
|
-
{% endif %}
|
|
17
|
-
<li><a href="{{ object.get_absolute_url }}">{{ object.name }}</a></li>
|
|
18
|
-
{% endblock breadcrumbs %}
|
|
19
3
|
{% block content_left_page %}
|
|
20
4
|
<div class="panel panel-default">
|
|
21
5
|
<div class="panel-heading">
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
<span class="mdi mdi-checkbox-marked-circle-outline" aria-hidden="true"></span> Show Images
|
|
11
11
|
</button>
|
|
12
12
|
<div class="btn-group" role="group">
|
|
13
|
-
<a href="{% url 'dcim:rack_elevation_list' %}{%
|
|
14
|
-
<a href="{% url 'dcim:rack_elevation_list' %}{%
|
|
13
|
+
<a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request face='front' %}" class="btn btn-default{% if rack_face == 'front' %} active{% endif %}">Front</a>
|
|
14
|
+
<a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request face='rear' %}" class="btn btn-default{% if rack_face == 'rear' %} active{% endif %}">Rear</a>
|
|
15
15
|
</div>
|
|
16
16
|
<div class="btn-group" role="group">
|
|
17
|
-
<a href="{% url 'dcim:rack_elevation_list' %}{%
|
|
18
|
-
<a href="{% url 'dcim:rack_elevation_list' %}{%
|
|
17
|
+
<a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request reverse=None %}" class="btn btn-default{% if not reverse %} active{% endif %}">Normal</a>
|
|
18
|
+
<a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request reverse='true' %}" class="btn btn-default{% if reverse %} active{% endif %}">Reversed</a>
|
|
19
19
|
</div>
|
|
20
20
|
{% endblock %}
|
|
21
21
|
|
|
@@ -1,51 +1,2 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Virtual Chassis</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<table class="table table-hover panel-body attr-table">
|
|
10
|
-
<tr>
|
|
11
|
-
<td>Domain</td>
|
|
12
|
-
<td>{{ object.domain|placeholder }}</td>
|
|
13
|
-
</tr>
|
|
14
|
-
<tr>
|
|
15
|
-
<td>Master</td>
|
|
16
|
-
<td>{{ object.master|hyperlinked_object }}</td>
|
|
17
|
-
</tr>
|
|
18
|
-
</table>
|
|
19
|
-
</div>
|
|
20
|
-
{% endblock content_left_page %}
|
|
21
|
-
|
|
22
|
-
{% block content_right_page %}
|
|
23
|
-
<div class="panel panel-default">
|
|
24
|
-
<div class="panel-heading">
|
|
25
|
-
<strong>Members</strong>
|
|
26
|
-
</div>
|
|
27
|
-
<table class="table table-hover panel-body attr-table">
|
|
28
|
-
<tr>
|
|
29
|
-
<th>Device</th>
|
|
30
|
-
<th>Position</th>
|
|
31
|
-
<th>Master</th>
|
|
32
|
-
<th>Priority</th>
|
|
33
|
-
</tr>
|
|
34
|
-
{% for vc_member in members %}
|
|
35
|
-
<tr{% if vc_member == device %} class="info"{% endif %}>
|
|
36
|
-
<td>{{ vc_member|hyperlinked_object }}</td>
|
|
37
|
-
<td><span class="badge badge-default">{{ vc_member.vc_position }}</span></td>
|
|
38
|
-
<td>{% if object.master == vc_member %}{{ True | render_boolean }}{% endif %}</td>
|
|
39
|
-
<td>{{ vc_member.vc_priority|placeholder }}</td>
|
|
40
|
-
</tr>
|
|
41
|
-
{% endfor %}
|
|
42
|
-
</table>
|
|
43
|
-
{% if perms.dcim.change_virtualchassis %}
|
|
44
|
-
<div class="panel-footer text-right noprint">
|
|
45
|
-
<a href="{% url 'dcim:virtualchassis_add_member' pk=object.pk %}?location={{ object.master.location.pk }}&rack={{ object.master.rack.pk }}" class="btn btn-primary btn-xs">
|
|
46
|
-
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Member
|
|
47
|
-
</a>
|
|
48
|
-
</div>
|
|
49
|
-
{% endif %}
|
|
50
|
-
</div>
|
|
51
|
-
{% endblock content_right_page %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -4202,6 +4202,47 @@ class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
4202
4202
|
# Sanity check:
|
|
4203
4203
|
self.assertBodyContains(response, "<th>Name</th>", html=True)
|
|
4204
4204
|
|
|
4205
|
+
def test_set_master_after_adding_member(self):
|
|
4206
|
+
"""Ensure master can be set for a member that was added via the Add Member flow."""
|
|
4207
|
+
self.add_permissions(
|
|
4208
|
+
"dcim.view_device",
|
|
4209
|
+
"dcim.view_virtualchassis",
|
|
4210
|
+
"dcim.change_virtualchassis",
|
|
4211
|
+
"dcim.change_device",
|
|
4212
|
+
)
|
|
4213
|
+
|
|
4214
|
+
# Create VC
|
|
4215
|
+
vc = VirtualChassis.objects.create(name="VC-test", domain="domain-test")
|
|
4216
|
+
|
|
4217
|
+
# Simulate adding a member via the separate "add-member" flow by creating the device with virtual_chassis
|
|
4218
|
+
member = Device.objects.create(
|
|
4219
|
+
device_type=self.devices[0].device_type,
|
|
4220
|
+
role=self.devices[0].role,
|
|
4221
|
+
status=self.devices[0].status,
|
|
4222
|
+
name="separately-added-device",
|
|
4223
|
+
location=self.devices[0].location,
|
|
4224
|
+
virtual_chassis=vc,
|
|
4225
|
+
vc_position=1,
|
|
4226
|
+
)
|
|
4227
|
+
|
|
4228
|
+
# Now edit the VC and set the master to the existing member
|
|
4229
|
+
payload_data = {
|
|
4230
|
+
"name": vc.name,
|
|
4231
|
+
"domain": vc.domain,
|
|
4232
|
+
"master": str(member.pk),
|
|
4233
|
+
# no members formset rows are required because the member already exists
|
|
4234
|
+
"form-TOTAL_FORMS": "0",
|
|
4235
|
+
"form-INITIAL_FORMS": "0",
|
|
4236
|
+
"form-MIN_NUM_FORMS": "0",
|
|
4237
|
+
"form-MAX_NUM_FORMS": "1000",
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
url = reverse("dcim:virtualchassis_edit", kwargs={"pk": vc.pk})
|
|
4241
|
+
self.client.post(url, data=payload_data, follow=True)
|
|
4242
|
+
|
|
4243
|
+
vc.refresh_from_db()
|
|
4244
|
+
self.assertEqual(vc.master, member)
|
|
4245
|
+
|
|
4205
4246
|
|
|
4206
4247
|
class PowerPanelTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
4207
4248
|
model = PowerPanel
|
nautobot/dcim/views.py
CHANGED
|
@@ -21,7 +21,7 @@ from django.urls import reverse
|
|
|
21
21
|
from django.utils.encoding import iri_to_uri
|
|
22
22
|
from django.utils.functional import cached_property
|
|
23
23
|
from django.utils.html import format_html
|
|
24
|
-
from django.utils.http import url_has_allowed_host_and_scheme
|
|
24
|
+
from django.utils.http import url_has_allowed_host_and_scheme, urlencode
|
|
25
25
|
from django.views.generic import View
|
|
26
26
|
from django_tables2 import RequestConfig
|
|
27
27
|
from rest_framework.decorators import action
|
|
@@ -42,6 +42,7 @@ from nautobot.core.ui.breadcrumbs import (
|
|
|
42
42
|
Breadcrumbs,
|
|
43
43
|
InstanceBreadcrumbItem,
|
|
44
44
|
ModelBreadcrumbItem,
|
|
45
|
+
ViewNameBreadcrumbItem,
|
|
45
46
|
)
|
|
46
47
|
from nautobot.core.ui.bulk_buttons import (
|
|
47
48
|
BulkDeleteButton,
|
|
@@ -49,6 +50,7 @@ from nautobot.core.ui.bulk_buttons import (
|
|
|
49
50
|
BulkRenameButton,
|
|
50
51
|
)
|
|
51
52
|
from nautobot.core.ui.choices import SectionChoices
|
|
53
|
+
from nautobot.core.ui.titles import Titles
|
|
52
54
|
from nautobot.core.utils.lookup import get_form_for_model
|
|
53
55
|
from nautobot.core.utils.permissions import get_permission_for_model
|
|
54
56
|
from nautobot.core.utils.requests import normalize_querydict
|
|
@@ -515,6 +517,7 @@ class RackGroupUIViewSet(NautobotUIViewSet):
|
|
|
515
517
|
if self.action == "retrieve" and instance:
|
|
516
518
|
racks = (
|
|
517
519
|
Rack.objects.restrict(request.user, "view")
|
|
520
|
+
# Note this filter - we want the table to include racks assigned to child rack groups as well
|
|
518
521
|
.filter(rack_group__in=instance.descendants(include_self=True))
|
|
519
522
|
.select_related("role", "location", "tenant")
|
|
520
523
|
)
|
|
@@ -590,6 +593,10 @@ class RackElevationListView(generic.ObjectListView):
|
|
|
590
593
|
filterset_form = forms.RackFilterForm
|
|
591
594
|
action_buttons = []
|
|
592
595
|
template_name = "dcim/rack_elevation_list.html"
|
|
596
|
+
view_titles = Titles(titles={"list": "Rack Elevation"})
|
|
597
|
+
breadcrumbs = Breadcrumbs(
|
|
598
|
+
items={"list": [ViewNameBreadcrumbItem(view_name="dcim:rack_elevation_list", label="Rack Elevation")]}
|
|
599
|
+
)
|
|
593
600
|
|
|
594
601
|
def extra_context(self):
|
|
595
602
|
racks = self.queryset
|
|
@@ -644,11 +651,15 @@ class RackReservationUIViewSet(NautobotUIViewSet):
|
|
|
644
651
|
|
|
645
652
|
object_detail_content = object_detail.ObjectDetailContent(
|
|
646
653
|
panels=(
|
|
647
|
-
object_detail.
|
|
654
|
+
object_detail.ObjectFieldsPanel(
|
|
648
655
|
section=SectionChoices.LEFT_HALF,
|
|
649
656
|
weight=100,
|
|
650
657
|
label="Rack",
|
|
651
|
-
|
|
658
|
+
fields=["rack__location", "rack__rack_group", "rack"],
|
|
659
|
+
key_transforms={
|
|
660
|
+
"rack__location": "Location",
|
|
661
|
+
"rack__rack_group": "Rack Group",
|
|
662
|
+
},
|
|
652
663
|
),
|
|
653
664
|
object_detail.ObjectFieldsPanel(
|
|
654
665
|
section=SectionChoices.LEFT_HALF,
|
|
@@ -664,23 +675,6 @@ class RackReservationUIViewSet(NautobotUIViewSet):
|
|
|
664
675
|
),
|
|
665
676
|
)
|
|
666
677
|
|
|
667
|
-
def get_extra_context(self, request, instance):
|
|
668
|
-
context = super().get_extra_context(request, instance)
|
|
669
|
-
if self.action == "retrieve":
|
|
670
|
-
context["rack_data"] = self.get_rack_context(instance)
|
|
671
|
-
return context
|
|
672
|
-
|
|
673
|
-
def get_rack_context(self, instance):
|
|
674
|
-
rack = getattr(instance, "rack", None)
|
|
675
|
-
if not rack:
|
|
676
|
-
return {}
|
|
677
|
-
|
|
678
|
-
return {
|
|
679
|
-
"location": rack.location,
|
|
680
|
-
"rack_group": rack.rack_group,
|
|
681
|
-
"rack": rack,
|
|
682
|
-
}
|
|
683
|
-
|
|
684
678
|
def get_object(self):
|
|
685
679
|
obj = super().get_object()
|
|
686
680
|
|
|
@@ -899,6 +893,7 @@ def make_bulk_tab(weight, tab_name, label, url_name, related_attr, table_class,
|
|
|
899
893
|
enable_bulk_actions=True,
|
|
900
894
|
form_id=form_id,
|
|
901
895
|
footer_buttons=bulk_footer_buttons(form_id=form_id, model=model),
|
|
896
|
+
include_paginator=True,
|
|
902
897
|
),
|
|
903
898
|
),
|
|
904
899
|
)
|
|
@@ -1889,13 +1884,14 @@ class PlatformUIViewSet(NautobotUIViewSet):
|
|
|
1889
1884
|
#
|
|
1890
1885
|
|
|
1891
1886
|
|
|
1892
|
-
class
|
|
1887
|
+
class DevicePageMixin:
|
|
1893
1888
|
breadcrumbs = Breadcrumbs(
|
|
1894
1889
|
items={
|
|
1895
1890
|
"detail": [
|
|
1896
1891
|
ModelBreadcrumbItem(model=Device),
|
|
1897
1892
|
ModelBreadcrumbItem(
|
|
1898
1893
|
model=Device,
|
|
1894
|
+
label=lambda c: c["object"].location,
|
|
1899
1895
|
reverse_query_params=lambda c: {"location": c["object"].location.pk},
|
|
1900
1896
|
),
|
|
1901
1897
|
InstanceBreadcrumbItem(
|
|
@@ -1910,6 +1906,49 @@ class DeviceBreadcrumbsMixin:
|
|
|
1910
1906
|
)
|
|
1911
1907
|
|
|
1912
1908
|
|
|
1909
|
+
class DeviceComponentPageMixin:
|
|
1910
|
+
"""
|
|
1911
|
+
This class hold the breadcrumbs paths for Device Components Pages like console ports.
|
|
1912
|
+
Depending on whether the component is associated with a device or a module, the appropriate breadcrumb path will be rendered.
|
|
1913
|
+
|
|
1914
|
+
For example:
|
|
1915
|
+
- Console Port assigned to the module: Modules / <Module name and link to details> / Console Ports (dcim/modules/<id>/console-ports/) / <Console Port name>
|
|
1916
|
+
- Console Port assigned to the device: Devices / <Device name and link to details> / Console Ports (dcim/devices/<id>/console-ports/) / <Console Port name>
|
|
1917
|
+
"""
|
|
1918
|
+
|
|
1919
|
+
breadcrumbs = Breadcrumbs(
|
|
1920
|
+
items={
|
|
1921
|
+
"detail": [
|
|
1922
|
+
ModelBreadcrumbItem(model=Device, should_render=lambda c: c["object"].device is not None),
|
|
1923
|
+
InstanceBreadcrumbItem(
|
|
1924
|
+
instance=lambda c: c["object"].device, should_render=lambda c: c["object"].device is not None
|
|
1925
|
+
),
|
|
1926
|
+
ViewNameBreadcrumbItem(
|
|
1927
|
+
view_name_key="device_breadcrumb_url",
|
|
1928
|
+
should_render=lambda c: c["object"].device is not None and c.get("device_breadcrumb_url"),
|
|
1929
|
+
reverse_kwargs=lambda c: {"pk": c["object"].device.pk},
|
|
1930
|
+
label=lambda c: c["object"]._meta.verbose_name_plural,
|
|
1931
|
+
),
|
|
1932
|
+
ModelBreadcrumbItem(model=Module, should_render=lambda c: c["object"].device is None),
|
|
1933
|
+
InstanceBreadcrumbItem(
|
|
1934
|
+
instance=lambda c: c["object"].module, should_render=lambda c: c["object"].device is None
|
|
1935
|
+
),
|
|
1936
|
+
ViewNameBreadcrumbItem(
|
|
1937
|
+
view_name_key="module_breadcrumb_url",
|
|
1938
|
+
should_render=lambda c: c["object"].device is None and c.get("module_breadcrumb_url"),
|
|
1939
|
+
reverse_kwargs=lambda c: {"pk": c["object"].module.pk},
|
|
1940
|
+
label=lambda c: c["object"]._meta.verbose_name_plural,
|
|
1941
|
+
),
|
|
1942
|
+
]
|
|
1943
|
+
}
|
|
1944
|
+
)
|
|
1945
|
+
view_titles = Titles(
|
|
1946
|
+
titles={
|
|
1947
|
+
"detail": "{% if object.device %}{{ object.device }}{% else %}{{ object.module.display }}{% endif %} / {{ object }}"
|
|
1948
|
+
}
|
|
1949
|
+
)
|
|
1950
|
+
|
|
1951
|
+
|
|
1913
1952
|
class DeviceListView(generic.ObjectListView):
|
|
1914
1953
|
queryset = Device.objects.select_related(
|
|
1915
1954
|
"device_type__manufacturer", # Needed for __str__() on device_type
|
|
@@ -1920,7 +1959,7 @@ class DeviceListView(generic.ObjectListView):
|
|
|
1920
1959
|
template_name = "dcim/device_list.html"
|
|
1921
1960
|
|
|
1922
1961
|
|
|
1923
|
-
class DeviceView(generic.ObjectView):
|
|
1962
|
+
class DeviceView(DevicePageMixin, generic.ObjectView):
|
|
1924
1963
|
queryset = Device.objects.select_related(
|
|
1925
1964
|
"cluster__cluster_group",
|
|
1926
1965
|
"controller_managed_device_group__controller",
|
|
@@ -1965,6 +2004,7 @@ class DeviceView(generic.ObjectView):
|
|
|
1965
2004
|
exclude_columns=["content_type"],
|
|
1966
2005
|
add_button_route=None,
|
|
1967
2006
|
related_field_name="member_id",
|
|
2007
|
+
include_paginator=True,
|
|
1968
2008
|
),
|
|
1969
2009
|
),
|
|
1970
2010
|
)
|
|
@@ -2175,7 +2215,7 @@ class DeviceView(generic.ObjectView):
|
|
|
2175
2215
|
}
|
|
2176
2216
|
|
|
2177
2217
|
|
|
2178
|
-
class DeviceComponentTabView(generic.ObjectView):
|
|
2218
|
+
class DeviceComponentTabView(DevicePageMixin, generic.ObjectView):
|
|
2179
2219
|
queryset = Device.objects.all()
|
|
2180
2220
|
|
|
2181
2221
|
def get_extra_context(self, request, instance):
|
|
@@ -2183,6 +2223,7 @@ class DeviceComponentTabView(generic.ObjectView):
|
|
|
2183
2223
|
module_count = instance.module_bays.filter(installed_module__isnull=False).count()
|
|
2184
2224
|
|
|
2185
2225
|
return {
|
|
2226
|
+
**super().get_extra_context(request, instance),
|
|
2186
2227
|
"modulebay_count": modulebay_count,
|
|
2187
2228
|
"module_count": f"{module_count}/{modulebay_count}",
|
|
2188
2229
|
}
|
|
@@ -2442,7 +2483,7 @@ class DeviceConfigView(generic.ObjectView):
|
|
|
2442
2483
|
}
|
|
2443
2484
|
|
|
2444
2485
|
|
|
2445
|
-
class DeviceConfigContextView(ObjectConfigContextView):
|
|
2486
|
+
class DeviceConfigContextView(DevicePageMixin, ObjectConfigContextView):
|
|
2446
2487
|
base_template = "dcim/device/base.html"
|
|
2447
2488
|
|
|
2448
2489
|
@cached_property
|
|
@@ -2453,7 +2494,7 @@ class DeviceConfigContextView(ObjectConfigContextView):
|
|
|
2453
2494
|
return Device.objects.annotate_config_context_data()
|
|
2454
2495
|
|
|
2455
2496
|
|
|
2456
|
-
class DeviceChangeLogView(ObjectChangeLogView):
|
|
2497
|
+
class DeviceChangeLogView(DevicePageMixin, ObjectChangeLogView):
|
|
2457
2498
|
base_template = "dcim/device/base.html"
|
|
2458
2499
|
|
|
2459
2500
|
|
|
@@ -3005,7 +3046,7 @@ class ConsolePortListView(generic.ObjectListView):
|
|
|
3005
3046
|
action_buttons = ("import", "export")
|
|
3006
3047
|
|
|
3007
3048
|
|
|
3008
|
-
class ConsolePortView(generic.ObjectView):
|
|
3049
|
+
class ConsolePortView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3009
3050
|
queryset = ConsolePort.objects.all()
|
|
3010
3051
|
|
|
3011
3052
|
def get_extra_context(self, request, instance):
|
|
@@ -3071,7 +3112,7 @@ class ConsoleServerPortListView(generic.ObjectListView):
|
|
|
3071
3112
|
action_buttons = ("import", "export")
|
|
3072
3113
|
|
|
3073
3114
|
|
|
3074
|
-
class ConsoleServerPortView(generic.ObjectView):
|
|
3115
|
+
class ConsoleServerPortView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3075
3116
|
queryset = ConsoleServerPort.objects.all()
|
|
3076
3117
|
|
|
3077
3118
|
def get_extra_context(self, request, instance):
|
|
@@ -3137,7 +3178,7 @@ class PowerPortListView(generic.ObjectListView):
|
|
|
3137
3178
|
action_buttons = ("import", "export")
|
|
3138
3179
|
|
|
3139
3180
|
|
|
3140
|
-
class PowerPortView(generic.ObjectView):
|
|
3181
|
+
class PowerPortView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3141
3182
|
queryset = PowerPort.objects.all()
|
|
3142
3183
|
|
|
3143
3184
|
def get_extra_context(self, request, instance):
|
|
@@ -3203,7 +3244,7 @@ class PowerOutletListView(generic.ObjectListView):
|
|
|
3203
3244
|
action_buttons = ("import", "export")
|
|
3204
3245
|
|
|
3205
3246
|
|
|
3206
|
-
class PowerOutletView(generic.ObjectView):
|
|
3247
|
+
class PowerOutletView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3207
3248
|
queryset = PowerOutlet.objects.all()
|
|
3208
3249
|
|
|
3209
3250
|
def get_extra_context(self, request, instance):
|
|
@@ -3269,7 +3310,10 @@ class InterfaceListView(generic.ObjectListView):
|
|
|
3269
3310
|
action_buttons = ("import", "export")
|
|
3270
3311
|
|
|
3271
3312
|
|
|
3272
|
-
class InterfaceView(
|
|
3313
|
+
class InterfaceView(
|
|
3314
|
+
DeviceComponentPageMixin,
|
|
3315
|
+
generic.ObjectView,
|
|
3316
|
+
):
|
|
3273
3317
|
queryset = Interface.objects.all()
|
|
3274
3318
|
|
|
3275
3319
|
def get_extra_context(self, request, instance):
|
|
@@ -3399,7 +3443,7 @@ class FrontPortListView(generic.ObjectListView):
|
|
|
3399
3443
|
action_buttons = ("import", "export")
|
|
3400
3444
|
|
|
3401
3445
|
|
|
3402
|
-
class FrontPortView(generic.ObjectView):
|
|
3446
|
+
class FrontPortView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3403
3447
|
queryset = FrontPort.objects.all()
|
|
3404
3448
|
|
|
3405
3449
|
def get_extra_context(self, request, instance):
|
|
@@ -3465,7 +3509,7 @@ class RearPortListView(generic.ObjectListView):
|
|
|
3465
3509
|
action_buttons = ("import", "export")
|
|
3466
3510
|
|
|
3467
3511
|
|
|
3468
|
-
class RearPortView(generic.ObjectView):
|
|
3512
|
+
class RearPortView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3469
3513
|
queryset = RearPort.objects.all()
|
|
3470
3514
|
|
|
3471
3515
|
def get_extra_context(self, request, instance):
|
|
@@ -3531,7 +3575,7 @@ class DeviceBayListView(generic.ObjectListView):
|
|
|
3531
3575
|
action_buttons = ("import", "export")
|
|
3532
3576
|
|
|
3533
3577
|
|
|
3534
|
-
class DeviceBayView(generic.ObjectView):
|
|
3578
|
+
class DeviceBayView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3535
3579
|
queryset = DeviceBay.objects.all()
|
|
3536
3580
|
|
|
3537
3581
|
def get_extra_context(self, request, instance):
|
|
@@ -3693,6 +3737,35 @@ class ModuleBayUIViewSet(ModuleBayCommonViewSetMixin, NautobotUIViewSet):
|
|
|
3693
3737
|
),
|
|
3694
3738
|
)
|
|
3695
3739
|
)
|
|
3740
|
+
breadcrumbs = Breadcrumbs(
|
|
3741
|
+
items={
|
|
3742
|
+
"detail": [
|
|
3743
|
+
# Breadcrumb path if ModuleBay is linked with device
|
|
3744
|
+
ModelBreadcrumbItem(model=Device, should_render=lambda c: c["object"].parent_device),
|
|
3745
|
+
InstanceBreadcrumbItem(
|
|
3746
|
+
instance=lambda c: c["object"].parent_device, should_render=lambda c: c["object"].parent_device
|
|
3747
|
+
),
|
|
3748
|
+
ViewNameBreadcrumbItem(
|
|
3749
|
+
view_name_key="device_breadcrumb_url",
|
|
3750
|
+
should_render=lambda c: c["object"].parent_device and c.get("device_breadcrumb_url"),
|
|
3751
|
+
reverse_kwargs=lambda c: {"pk": c["object"].parent_device.pk},
|
|
3752
|
+
label=lambda c: c["object"]._meta.verbose_name_plural,
|
|
3753
|
+
),
|
|
3754
|
+
# Breadcrumb path if ModuleBay is linked with module
|
|
3755
|
+
ModelBreadcrumbItem(model=Module, should_render=lambda c: c["object"].parent_device is None),
|
|
3756
|
+
InstanceBreadcrumbItem(
|
|
3757
|
+
instance=lambda c: c["object"].parent_module,
|
|
3758
|
+
should_render=lambda c: c["object"].parent_device is None,
|
|
3759
|
+
),
|
|
3760
|
+
ViewNameBreadcrumbItem(
|
|
3761
|
+
view_name_key="module_breadcrumb_url",
|
|
3762
|
+
should_render=lambda c: c["object"].parent_device is None and c.get("module_breadcrumb_url"),
|
|
3763
|
+
reverse_kwargs=lambda c: {"pk": c["object"].parent_module.pk},
|
|
3764
|
+
label=lambda c: c["object"]._meta.verbose_name_plural,
|
|
3765
|
+
),
|
|
3766
|
+
]
|
|
3767
|
+
}
|
|
3768
|
+
)
|
|
3696
3769
|
|
|
3697
3770
|
def get_extra_context(self, request, instance):
|
|
3698
3771
|
context = super().get_extra_context(request, instance)
|
|
@@ -3746,7 +3819,7 @@ class InventoryItemListView(generic.ObjectListView):
|
|
|
3746
3819
|
action_buttons = ("import", "export")
|
|
3747
3820
|
|
|
3748
3821
|
|
|
3749
|
-
class InventoryItemView(generic.ObjectView):
|
|
3822
|
+
class InventoryItemView(DeviceComponentPageMixin, generic.ObjectView):
|
|
3750
3823
|
queryset = InventoryItem.objects.all().select_related("device", "manufacturer", "software_version")
|
|
3751
3824
|
|
|
3752
3825
|
def get_extra_context(self, request, instance):
|
|
@@ -4106,6 +4179,10 @@ class ConsoleConnectionsListView(ConnectionsListView):
|
|
|
4106
4179
|
table = tables.ConsoleConnectionTable
|
|
4107
4180
|
template_name = "dcim/console_port_connection_list.html"
|
|
4108
4181
|
action_buttons = ("export",)
|
|
4182
|
+
view_titles = Titles(titles={"list": "Console Connections"})
|
|
4183
|
+
breadcrumbs = Breadcrumbs(
|
|
4184
|
+
items={"list": [ViewNameBreadcrumbItem(view_name="dcim:console_connections_list", label="Console Connections")]}
|
|
4185
|
+
)
|
|
4109
4186
|
|
|
4110
4187
|
def extra_context(self):
|
|
4111
4188
|
return {
|
|
@@ -4122,6 +4199,10 @@ class PowerConnectionsListView(ConnectionsListView):
|
|
|
4122
4199
|
table = tables.PowerConnectionTable
|
|
4123
4200
|
template_name = "dcim/power_port_connection_list.html"
|
|
4124
4201
|
action_buttons = ("export",)
|
|
4202
|
+
view_titles = Titles(titles={"list": "Power Connections"})
|
|
4203
|
+
breadcrumbs = Breadcrumbs(
|
|
4204
|
+
items={"list": [ViewNameBreadcrumbItem(view_name="dcim:power_connections_list", label="Power Connections")]}
|
|
4205
|
+
)
|
|
4125
4206
|
|
|
4126
4207
|
def extra_context(self):
|
|
4127
4208
|
return {
|
|
@@ -4138,6 +4219,12 @@ class InterfaceConnectionsListView(ConnectionsListView):
|
|
|
4138
4219
|
table = tables.InterfaceConnectionTable
|
|
4139
4220
|
template_name = "dcim/interface_connection_list.html"
|
|
4140
4221
|
action_buttons = ("export",)
|
|
4222
|
+
view_titles = Titles(titles={"list": "Interface Connections"})
|
|
4223
|
+
breadcrumbs = Breadcrumbs(
|
|
4224
|
+
items={
|
|
4225
|
+
"list": [ViewNameBreadcrumbItem(view_name="dcim:interface_connections_list", label="Interface Connections")]
|
|
4226
|
+
}
|
|
4227
|
+
)
|
|
4141
4228
|
|
|
4142
4229
|
def __init__(self, *args, **kwargs):
|
|
4143
4230
|
super().__init__(*args, **kwargs)
|
|
@@ -4180,10 +4267,50 @@ class VirtualChassisUIViewSet(NautobotUIViewSet):
|
|
|
4180
4267
|
bulk_update_form_class = forms.VirtualChassisBulkEditForm
|
|
4181
4268
|
filterset_class = filters.VirtualChassisFilterSet
|
|
4182
4269
|
filterset_form_class = forms.VirtualChassisFilterForm
|
|
4183
|
-
form_class = forms.VirtualChassisCreateForm
|
|
4184
4270
|
serializer_class = serializers.VirtualChassisSerializer
|
|
4185
4271
|
table_class = tables.VirtualChassisTable
|
|
4186
4272
|
queryset = VirtualChassis.objects.all()
|
|
4273
|
+
create_form_class = forms.VirtualChassisCreateForm
|
|
4274
|
+
update_form_class = forms.VirtualChassisForm
|
|
4275
|
+
|
|
4276
|
+
class MembersObjectsTablePanel(object_detail.ObjectsTablePanel):
|
|
4277
|
+
def _get_table_add_url(self, context):
|
|
4278
|
+
obj = get_obj_from_context(context)
|
|
4279
|
+
request = context["request"]
|
|
4280
|
+
return_url = context.get("return_url", obj.get_absolute_url())
|
|
4281
|
+
|
|
4282
|
+
if not request.user.has_perm("dcim.change_virtualchassis"):
|
|
4283
|
+
return None
|
|
4284
|
+
|
|
4285
|
+
params = []
|
|
4286
|
+
master = obj.master
|
|
4287
|
+
|
|
4288
|
+
if master is not None:
|
|
4289
|
+
if master.location is not None:
|
|
4290
|
+
params.append(("location", master.location.pk))
|
|
4291
|
+
|
|
4292
|
+
if master.rack is not None:
|
|
4293
|
+
params.append(("rack", master.rack.pk))
|
|
4294
|
+
|
|
4295
|
+
params.append(("return_url", return_url))
|
|
4296
|
+
return reverse("dcim:virtualchassis_add_member", kwargs={"pk": obj.pk}) + "?" + urlencode(params)
|
|
4297
|
+
|
|
4298
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
4299
|
+
panels=[
|
|
4300
|
+
object_detail.ObjectFieldsPanel(
|
|
4301
|
+
section=SectionChoices.LEFT_HALF,
|
|
4302
|
+
weight=100,
|
|
4303
|
+
fields="__all__",
|
|
4304
|
+
),
|
|
4305
|
+
MembersObjectsTablePanel(
|
|
4306
|
+
section=SectionChoices.RIGHT_HALF,
|
|
4307
|
+
weight=100,
|
|
4308
|
+
table_class=tables.VirtualChassisMembersTable,
|
|
4309
|
+
table_filter="virtual_chassis",
|
|
4310
|
+
table_title="Members",
|
|
4311
|
+
),
|
|
4312
|
+
]
|
|
4313
|
+
)
|
|
4187
4314
|
|
|
4188
4315
|
def get_extra_context(self, request, instance):
|
|
4189
4316
|
context = super().get_extra_context(request, instance)
|
|
@@ -4213,10 +4340,6 @@ class VirtualChassisUIViewSet(NautobotUIViewSet):
|
|
|
4213
4340
|
}
|
|
4214
4341
|
)
|
|
4215
4342
|
|
|
4216
|
-
elif self.action == "retrieve":
|
|
4217
|
-
members = Device.objects.restrict(request.user).filter(virtual_chassis=instance)
|
|
4218
|
-
context.update({"members": members})
|
|
4219
|
-
|
|
4220
4343
|
return context
|
|
4221
4344
|
|
|
4222
4345
|
def form_save(self, form, **kwargs):
|
|
@@ -4794,6 +4917,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
|
|
|
4794
4917
|
table_filter="software_image_files",
|
|
4795
4918
|
tab_id="device_types",
|
|
4796
4919
|
add_button_route=None,
|
|
4920
|
+
include_paginator=True,
|
|
4797
4921
|
),
|
|
4798
4922
|
),
|
|
4799
4923
|
),
|
|
@@ -4812,6 +4936,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
|
|
|
4812
4936
|
tab_id="devices",
|
|
4813
4937
|
table_title="Devices overridden to use this file",
|
|
4814
4938
|
add_button_route=None,
|
|
4939
|
+
include_paginator=True,
|
|
4815
4940
|
),
|
|
4816
4941
|
),
|
|
4817
4942
|
),
|
|
@@ -4830,6 +4955,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
|
|
|
4830
4955
|
tab_id="inventory_items",
|
|
4831
4956
|
table_title="Inventory items overridden to use this file",
|
|
4832
4957
|
add_button_route=None,
|
|
4958
|
+
include_paginator=True,
|
|
4833
4959
|
),
|
|
4834
4960
|
),
|
|
4835
4961
|
),
|
|
@@ -4848,6 +4974,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
|
|
|
4848
4974
|
tab_id="virtual_machines",
|
|
4849
4975
|
table_title="Virtual machines overridden to use this file",
|
|
4850
4976
|
add_button_route=None,
|
|
4977
|
+
include_paginator=True,
|
|
4851
4978
|
),
|
|
4852
4979
|
),
|
|
4853
4980
|
),
|
|
@@ -4993,6 +5120,7 @@ class ControllerUIViewSet(NautobotUIViewSet):
|
|
|
4993
5120
|
add_button_route=None,
|
|
4994
5121
|
select_related_fields=["wireless_network"],
|
|
4995
5122
|
exclude_columns=["controller"],
|
|
5123
|
+
include_paginator=True,
|
|
4996
5124
|
),
|
|
4997
5125
|
),
|
|
4998
5126
|
),
|
|
@@ -5056,6 +5184,7 @@ class ControllerManagedDeviceGroupUIViewSet(NautobotUIViewSet):
|
|
|
5056
5184
|
tab_id="wireless_networks",
|
|
5057
5185
|
add_button_route=None,
|
|
5058
5186
|
exclude_columns=["controller_managed_device_group", "controller"],
|
|
5187
|
+
include_paginator=True,
|
|
5059
5188
|
),
|
|
5060
5189
|
),
|
|
5061
5190
|
),
|
|
@@ -5074,6 +5203,7 @@ class ControllerManagedDeviceGroupUIViewSet(NautobotUIViewSet):
|
|
|
5074
5203
|
table_filter="controller_managed_device_groups",
|
|
5075
5204
|
tab_id="radio_profiles",
|
|
5076
5205
|
add_button_route=None,
|
|
5206
|
+
include_paginator=True,
|
|
5077
5207
|
),
|
|
5078
5208
|
),
|
|
5079
5209
|
),
|
|
@@ -209,7 +209,7 @@ class RelationshipFilter(django_filters.ModelMultipleChoiceFilter):
|
|
|
209
209
|
return query
|
|
210
210
|
|
|
211
211
|
def filter(self, qs, value):
|
|
212
|
-
if not value or any(v in EMPTY_VALUES for v in value):
|
|
212
|
+
if not value or any(v in EMPTY_VALUES for v in value) or (hasattr(value, "exists") and not value.exists()):
|
|
213
213
|
return qs
|
|
214
214
|
|
|
215
215
|
query = self.generate_query(value)
|
nautobot/extras/forms/forms.py
CHANGED
|
@@ -144,6 +144,7 @@ __all__ = (
|
|
|
144
144
|
"CustomLinkFilterForm",
|
|
145
145
|
"CustomLinkForm",
|
|
146
146
|
"DynamicGroupBulkAssignForm",
|
|
147
|
+
"DynamicGroupBulkEditForm",
|
|
147
148
|
"DynamicGroupFilterForm",
|
|
148
149
|
"DynamicGroupForm",
|
|
149
150
|
"DynamicGroupMembershipFormSet",
|
|
@@ -704,6 +705,20 @@ class CustomLinkFilterForm(BootstrapMixin, forms.Form):
|
|
|
704
705
|
#
|
|
705
706
|
# Dynamic Groups
|
|
706
707
|
#
|
|
708
|
+
class DynamicGroupBulkEditForm(NautobotBulkEditForm):
|
|
709
|
+
pk = forms.ModelMultipleChoiceField(queryset=DynamicGroup.objects.all(), widget=forms.MultipleHiddenInput())
|
|
710
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
711
|
+
tenant = DynamicModelChoiceField(
|
|
712
|
+
queryset=Tenant.objects.all(),
|
|
713
|
+
required=False,
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
class Meta:
|
|
717
|
+
model = DynamicGroup
|
|
718
|
+
fields = [
|
|
719
|
+
"description",
|
|
720
|
+
"tenant",
|
|
721
|
+
]
|
|
707
722
|
|
|
708
723
|
|
|
709
724
|
class DynamicGroupForm(TenancyForm, NautobotModelForm):
|