nautobot 2.4.8__py3-none-any.whl → 2.4.9__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/circuits/templates/circuits/circuittype.html +1 -1
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +1 -39
- nautobot/circuits/views.py +18 -23
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +4 -111
- nautobot/cloud/views.py +56 -25
- nautobot/core/celery/schedulers.py +1 -0
- nautobot/core/filters.py +1 -1
- nautobot/core/graphql/schema.py +1 -0
- nautobot/core/jobs/__init__.py +14 -3
- nautobot/core/tables.py +13 -6
- nautobot/core/testing/views.py +27 -2
- nautobot/core/tests/test_jobs.py +113 -0
- nautobot/core/tests/test_ui.py +53 -1
- nautobot/core/tests/test_utils.py +11 -0
- nautobot/core/ui/object_detail.py +19 -12
- nautobot/core/utils/filtering.py +3 -0
- nautobot/core/views/renderers.py +1 -1
- nautobot/dcim/forms.py +10 -0
- nautobot/dcim/templates/dcim/devicefamily_retrieve.html +1 -43
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +1 -59
- nautobot/dcim/templates/dcim/devicetype.html +2 -217
- nautobot/dcim/templates/dcim/devicetype_edit.html +2 -32
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +217 -0
- nautobot/dcim/templates/dcim/devicetype_update.html +32 -0
- nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +1 -84
- nautobot/dcim/templates/dcim/rack_elevation.html +14 -0
- nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -68
- nautobot/dcim/tests/integration/test_fileinputpicker.py +1 -1
- nautobot/dcim/urls.py +1 -36
- nautobot/dcim/views.py +133 -81
- nautobot/extras/api/views.py +4 -6
- nautobot/extras/migrations/0024_job_data_migration.py +1 -1
- nautobot/extras/models/jobs.py +78 -62
- nautobot/extras/tables.py +11 -1
- nautobot/extras/templates/extras/computedfield_retrieve.html +1 -55
- nautobot/extras/templates/extras/inc/job_tiles.html +1 -1
- nautobot/extras/templates/extras/jobresult.html +1 -1
- nautobot/extras/templates/extras/metadatatype_retrieve.html +1 -66
- nautobot/extras/templates/extras/scheduledjob.html +25 -9
- nautobot/extras/tests/test_api.py +1 -1
- nautobot/extras/tests/test_views.py +15 -2
- nautobot/extras/utils.py +18 -16
- nautobot/extras/views.py +65 -26
- nautobot/ipam/tables.py +3 -4
- nautobot/project-static/docs/404.html +4 -4
- nautobot/project-static/docs/apps/index.html +4 -4
- nautobot/project-static/docs/apps/nautobot-apps.html +4 -4
- nautobot/project-static/docs/assets/javascripts/{bundle.c8b220af.min.js → bundle.13a4f30d.min.js} +4 -4
- nautobot/project-static/docs/assets/javascripts/{bundle.c8b220af.min.js.map → bundle.13a4f30d.min.js.map} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.f8cc74c7.min.js → search.d50fe291.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.f8cc74c7.min.js.map → search.d50fe291.min.js.map} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.2afb09e1.min.css → main.342714a4.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.2afb09e1.min.css.map → main.342714a4.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +4 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +36 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +4 -4
- nautobot/project-static/docs/development/apps/api/configuration-view.html +4 -4
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/global-search.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/graphql.html +4 -4
- nautobot/project-static/docs/development/apps/api/models/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +4 -4
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +4 -4
- nautobot/project-static/docs/development/apps/api/prometheus.html +4 -4
- nautobot/project-static/docs/development/apps/api/setup.html +4 -4
- nautobot/project-static/docs/development/apps/api/testing.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +4 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/base-template.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/index.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/notes.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +4 -4
- nautobot/project-static/docs/development/apps/api/views/urls.html +4 -4
- nautobot/project-static/docs/development/apps/index.html +4 -4
- nautobot/project-static/docs/development/apps/migration/code-updates.html +4 -4
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +4 -4
- nautobot/project-static/docs/development/apps/migration/from-v1.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +4 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +4 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +4 -4
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +4 -4
- nautobot/project-static/docs/development/core/application-registry.html +4 -4
- nautobot/project-static/docs/development/core/best-practices.html +4 -4
- nautobot/project-static/docs/development/core/bootstrap-ui.html +4 -4
- nautobot/project-static/docs/development/core/caching.html +4 -4
- nautobot/project-static/docs/development/core/controllers.html +4 -4
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +41 -55
- nautobot/project-static/docs/development/core/generic-views.html +4 -4
- nautobot/project-static/docs/development/core/getting-started.html +4 -4
- nautobot/project-static/docs/development/core/homepage.html +4 -4
- nautobot/project-static/docs/development/core/index.html +4 -4
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +4 -4
- nautobot/project-static/docs/development/core/model-checklist.html +4 -4
- nautobot/project-static/docs/development/core/model-features.html +4 -4
- nautobot/project-static/docs/development/core/natural-keys.html +4 -4
- nautobot/project-static/docs/development/core/navigation-menu.html +4 -4
- nautobot/project-static/docs/development/core/release-checklist.html +4 -4
- nautobot/project-static/docs/development/core/role-internals.html +4 -4
- nautobot/project-static/docs/development/core/settings.html +4 -4
- nautobot/project-static/docs/development/core/style-guide.html +4 -4
- nautobot/project-static/docs/development/core/templates.html +4 -4
- nautobot/project-static/docs/development/core/testing.html +4 -4
- nautobot/project-static/docs/development/core/ui-component-framework.html +4 -4
- nautobot/project-static/docs/development/core/user-preferences.html +4 -4
- nautobot/project-static/docs/development/index.html +4 -4
- nautobot/project-static/docs/development/jobs/getting-started.html +4 -4
- nautobot/project-static/docs/development/jobs/index.html +4 -4
- nautobot/project-static/docs/development/jobs/installation.html +4 -4
- nautobot/project-static/docs/development/jobs/job-extensions.html +4 -4
- nautobot/project-static/docs/development/jobs/job-logging.html +4 -4
- nautobot/project-static/docs/development/jobs/job-patterns.html +4 -4
- nautobot/project-static/docs/development/jobs/job-structure.html +4 -4
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +4 -4
- nautobot/project-static/docs/development/jobs/testing.html +4 -4
- nautobot/project-static/docs/index.html +4 -4
- nautobot/project-static/docs/overview/application_stack.html +4 -4
- nautobot/project-static/docs/overview/design_philosophy.html +4 -4
- nautobot/project-static/docs/release-notes/index.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.0.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.1.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.2.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.3.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.4.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.5.html +4 -4
- nautobot/project-static/docs/release-notes/version-1.6.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.0.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.1.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.2.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.3.html +4 -4
- nautobot/project-static/docs/release-notes/version-2.4.html +190 -4
- nautobot/project-static/docs/requirements.txt +1 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +298 -298
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +4 -4
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +4 -4
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +4 -4
- nautobot/project-static/docs/user-guide/administration/installation/services.html +4 -4
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +4 -4
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +4 -4
- nautobot/project-static/docs/user-guide/administration/security/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/security/notices.html +4 -4
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +4 -4
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +4 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +4 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +4 -4
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +4 -4
- nautobot/project-static/docs/user-guide/index.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +4 -4
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +4 -4
- nautobot/project-static/js/forms.js +0 -14
- nautobot/wireless/tables.py +1 -0
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -55
- nautobot/wireless/views.py +33 -28
- {nautobot-2.4.8.dist-info → nautobot-2.4.9.dist-info}/METADATA +3 -3
- {nautobot-2.4.8.dist-info → nautobot-2.4.9.dist-info}/RECORD +364 -361
- {nautobot-2.4.8.dist-info → nautobot-2.4.9.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.8.dist-info → nautobot-2.4.9.dist-info}/NOTICE +0 -0
- {nautobot-2.4.8.dist-info → nautobot-2.4.9.dist-info}/WHEEL +0 -0
- {nautobot-2.4.8.dist-info → nautobot-2.4.9.dist-info}/entry_points.txt +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
{% extends 'circuits/circuittype_retrieve.html' %}
|
|
2
|
-
{% comment %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -1,40 +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>Circuit Type</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<table class="table table-hover panel-body attr-table">
|
|
10
|
-
<tr>
|
|
11
|
-
<td>Description</td>
|
|
12
|
-
<td>{{ object.description|placeholder }}</td>
|
|
13
|
-
</tr>
|
|
14
|
-
<tr>
|
|
15
|
-
<td>Circuits</td>
|
|
16
|
-
<td>
|
|
17
|
-
<a href="{% url 'circuits:circuit_list' %}?circuit_type={{ object.pk }}">{{ circuits_table.rows|length }}</a>
|
|
18
|
-
</td>
|
|
19
|
-
</tr>
|
|
20
|
-
</table>
|
|
21
|
-
</div>
|
|
22
|
-
{% endblock content_left_page %}
|
|
23
|
-
|
|
24
|
-
{% block content_full_width_page %}
|
|
25
|
-
<div class="panel panel-default">
|
|
26
|
-
<div class="panel-heading">
|
|
27
|
-
<strong>Circuits</strong>
|
|
28
|
-
</div>
|
|
29
|
-
{% include 'inc/table.html' with table=circuits_table %}
|
|
30
|
-
{% if perms.circuits.add_circuit %}
|
|
31
|
-
<div class="panel-footer text-right noprint">
|
|
32
|
-
<a href="{% url 'circuits:circuit_add' %}?type={{ object.pk }}" class="btn btn-xs btn-primary">
|
|
33
|
-
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add circuit
|
|
34
|
-
</a>
|
|
35
|
-
</div>
|
|
36
|
-
{% endif %}
|
|
37
|
-
</div>
|
|
38
|
-
{% include 'inc/paginator.html' with paginator=circuits_table.paginator page=circuits_table.page %}
|
|
39
|
-
<div class="row"></div>
|
|
40
|
-
{% endblock content_full_width_page %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
nautobot/circuits/views.py
CHANGED
|
@@ -2,7 +2,6 @@ from django.contrib import messages
|
|
|
2
2
|
from django.db import transaction
|
|
3
3
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
4
4
|
from django.utils.html import format_html
|
|
5
|
-
from django_tables2 import RequestConfig
|
|
6
5
|
|
|
7
6
|
from nautobot.core.forms import ConfirmationForm
|
|
8
7
|
from nautobot.core.templatetags.helpers import bettertitle, humanize_speed, placeholder
|
|
@@ -14,7 +13,6 @@ from nautobot.core.ui.object_detail import (
|
|
|
14
13
|
)
|
|
15
14
|
from nautobot.core.ui.utils import render_component_template
|
|
16
15
|
from nautobot.core.views import generic
|
|
17
|
-
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
18
16
|
from nautobot.core.views.viewsets import NautobotUIViewSet
|
|
19
17
|
|
|
20
18
|
from . import filters, forms, tables
|
|
@@ -32,27 +30,24 @@ class CircuitTypeUIViewSet(NautobotUIViewSet):
|
|
|
32
30
|
serializer_class = serializers.CircuitTypeSerializer
|
|
33
31
|
table_class = tables.CircuitTypeTable
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
RequestConfig(request, paginate).configure(circuits_table)
|
|
54
|
-
context["circuits_table"] = circuits_table
|
|
55
|
-
return context
|
|
33
|
+
object_detail_content = ObjectDetailContent(
|
|
34
|
+
panels=(
|
|
35
|
+
ObjectFieldsPanel(
|
|
36
|
+
section=SectionChoices.LEFT_HALF,
|
|
37
|
+
weight=100,
|
|
38
|
+
fields="__all__",
|
|
39
|
+
),
|
|
40
|
+
ObjectsTablePanel(
|
|
41
|
+
section=SectionChoices.FULL_WIDTH,
|
|
42
|
+
weight=100,
|
|
43
|
+
table_class=tables.CircuitTable,
|
|
44
|
+
table_filter="circuit_type",
|
|
45
|
+
select_related_fields=["circuit_type", "tenant"],
|
|
46
|
+
prefetch_related_fields=["circuit_terminations__location"],
|
|
47
|
+
exclude_columns=["circuit_type"],
|
|
48
|
+
),
|
|
49
|
+
),
|
|
50
|
+
)
|
|
56
51
|
|
|
57
52
|
|
|
58
53
|
class CircuitTerminationUIViewSet(NautobotUIViewSet):
|
|
@@ -1,111 +1,4 @@
|
|
|
1
|
-
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{%
|
|
5
|
-
<li><a href="{% url 'cloud:cloudresourcetype_list' %}?provider={{ object.provider.pk }}">{{ object.provider }}</a></li>
|
|
6
|
-
{% endblock extra_breadcrumbs %}
|
|
7
|
-
|
|
8
|
-
{% block extra_nav_tabs %}
|
|
9
|
-
{% if networks_count %}
|
|
10
|
-
<li role="presentation"{% if request.GET.tab == 'networks' %} class="active"{% endif %}>
|
|
11
|
-
<a href="{{ object.get_absolute_url }}#networks" onclick="switch_tab(this.href, reload=false)" aria-controls="networks" role="tab" data-toggle="tab">
|
|
12
|
-
Cloud Networks {% badge networks_count %}
|
|
13
|
-
</a>
|
|
14
|
-
</li>
|
|
15
|
-
{% endif %}
|
|
16
|
-
{% if services_count %}
|
|
17
|
-
<li role="presentation"{% if request.GET.tab == 'services' %} class="active"{% endif %}>
|
|
18
|
-
<a href="{{ object.get_absolute_url }}#services" onclick="switch_tab(this.href, reload=false)" aria-controls="services" role="tab" data-toggle="tab">
|
|
19
|
-
Cloud Services {% badge services_count %}
|
|
20
|
-
</a>
|
|
21
|
-
</li>
|
|
22
|
-
{% endif %}
|
|
23
|
-
{% endblock extra_nav_tabs %}
|
|
24
|
-
|
|
25
|
-
{% block content_left_page %}
|
|
26
|
-
<div class="panel panel-default">
|
|
27
|
-
<div class="panel-heading">
|
|
28
|
-
<strong>Cloud Resource Type</strong>
|
|
29
|
-
</div>
|
|
30
|
-
<table class="table table-hover panel-body attr-table">
|
|
31
|
-
<tr>
|
|
32
|
-
<td>Name</td>
|
|
33
|
-
<td>
|
|
34
|
-
{{ object.name }}
|
|
35
|
-
</td>
|
|
36
|
-
</tr>
|
|
37
|
-
<tr>
|
|
38
|
-
<td>Provider</td>
|
|
39
|
-
<td>{{ object.provider|hyperlinked_object }}</td>
|
|
40
|
-
</tr>
|
|
41
|
-
<tr>
|
|
42
|
-
<td>Content Type(s)</td>
|
|
43
|
-
<td>
|
|
44
|
-
{% if object.content_types.all %}
|
|
45
|
-
<ul>
|
|
46
|
-
{% for content_type in object.content_types.all %}
|
|
47
|
-
<li>{{ content_type }}</li>
|
|
48
|
-
{% endfor %}
|
|
49
|
-
</ul>
|
|
50
|
-
{% else %}
|
|
51
|
-
{{ None|placeholder }}
|
|
52
|
-
{% endif %}
|
|
53
|
-
</td>
|
|
54
|
-
</tr>
|
|
55
|
-
<tr>
|
|
56
|
-
<td>Description</td>
|
|
57
|
-
<td>{{ object.description|placeholder }}</td>
|
|
58
|
-
</tr>
|
|
59
|
-
</table>
|
|
60
|
-
</div>
|
|
61
|
-
{% endblock content_left_page %}
|
|
62
|
-
|
|
63
|
-
{% block content_right_page %}
|
|
64
|
-
<div class="panel panel-default">
|
|
65
|
-
<div class="panel-heading">
|
|
66
|
-
<strong>Config Schema</strong>
|
|
67
|
-
</div>
|
|
68
|
-
<div class="panel-body">
|
|
69
|
-
<pre>{{ object.config_schema|render_json }}</pre>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
{% endblock content_right_page %}
|
|
73
|
-
|
|
74
|
-
{% block extra_tab_content %}
|
|
75
|
-
{% if networks_count %}
|
|
76
|
-
<div id="networks" role="tabpanel" class="tab-pane {% if not active_tab and not request.GET.tab or request.GET.tab == "networks" %}active{% else %}fade{% endif %}">
|
|
77
|
-
<div class="panel panel-default">
|
|
78
|
-
<div class="panel-heading">
|
|
79
|
-
<strong>Cloud Networks</strong>
|
|
80
|
-
</div>
|
|
81
|
-
{% include 'inc/table.html' with table=networks_table %}
|
|
82
|
-
{% if perms.cloud.add_cloudnetwork %}
|
|
83
|
-
<div class="panel-footer text-right noprint">
|
|
84
|
-
<a href="{% url 'cloud:cloudnetwork_add' %}?cloud_resource_type={{ object.pk }}" class="btn btn-xs btn-primary">
|
|
85
|
-
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add cloud network
|
|
86
|
-
</a>
|
|
87
|
-
</div>
|
|
88
|
-
{% endif %}
|
|
89
|
-
</div>
|
|
90
|
-
{% include 'inc/paginator.html' with paginator=networks_table.paginator page=networks_table.page %}
|
|
91
|
-
</div>
|
|
92
|
-
{% endif %}
|
|
93
|
-
{% if services_count %}
|
|
94
|
-
<div id="services" role="tabpanel" class="tab-pane {% if not active_tab and not request.GET.tab or request.GET.tab == "services" %}active{% else %}fade{% endif %}">
|
|
95
|
-
<div class="panel panel-default">
|
|
96
|
-
<div class="panel-heading">
|
|
97
|
-
<strong>Cloud Services</strong>
|
|
98
|
-
</div>
|
|
99
|
-
{% include 'inc/table.html' with table=services_table %}
|
|
100
|
-
{% if perms.cloud.add_cloudservice %}
|
|
101
|
-
<div class="panel-footer text-right noprint">
|
|
102
|
-
<a href="{% url 'cloud:cloudservice_add' %}?cloud_resource_type={{ object.pk }}" class="btn btn-xs btn-primary">
|
|
103
|
-
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add cloud service
|
|
104
|
-
</a>
|
|
105
|
-
</div>
|
|
106
|
-
{% endif %}
|
|
107
|
-
</div>
|
|
108
|
-
{% include 'inc/paginator.html' with paginator=services_table.paginator page=services_table.page %}
|
|
109
|
-
</div>
|
|
110
|
-
{% endif %}
|
|
111
|
-
{% endblock extra_tab_content %}
|
|
1
|
+
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
+
{% block extra_breadcrumbs %}
|
|
3
|
+
<li><a href="{% url 'cloud:cloudresourcetype_list' %}?provider={{ object.provider.pk }}">{{ object.provider }}</a></li>
|
|
4
|
+
{% endblock extra_breadcrumbs %}
|
nautobot/cloud/views.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from django_tables2 import RequestConfig
|
|
2
1
|
from rest_framework.decorators import action
|
|
3
2
|
from rest_framework.response import Response
|
|
4
3
|
|
|
@@ -33,7 +32,6 @@ from nautobot.cloud.models import CloudAccount, CloudNetwork, CloudResourceType,
|
|
|
33
32
|
from nautobot.cloud.tables import CloudAccountTable, CloudNetworkTable, CloudResourceTypeTable, CloudServiceTable
|
|
34
33
|
from nautobot.core.ui import object_detail
|
|
35
34
|
from nautobot.core.ui.choices import SectionChoices
|
|
36
|
-
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
37
35
|
from nautobot.core.views.viewsets import NautobotUIViewSet
|
|
38
36
|
from nautobot.ipam.tables import PrefixTable
|
|
39
37
|
|
|
@@ -181,31 +179,64 @@ class CloudResourceTypeUIViewSet(NautobotUIViewSet):
|
|
|
181
179
|
form_class = CloudResourceTypeForm
|
|
182
180
|
bulk_update_form_class = CloudResourceTypeBulkEditForm
|
|
183
181
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
182
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
183
|
+
panels=(
|
|
184
|
+
object_detail.ObjectFieldsPanel(
|
|
185
|
+
section=SectionChoices.LEFT_HALF,
|
|
186
|
+
weight=100,
|
|
187
|
+
fields=("name", "provider", "content_types", "description"),
|
|
188
|
+
),
|
|
189
|
+
object_detail.ObjectTextPanel(
|
|
190
|
+
section=SectionChoices.RIGHT_HALF,
|
|
191
|
+
weight=100,
|
|
192
|
+
object_field="config_schema",
|
|
193
|
+
label="Config Schema",
|
|
194
|
+
render_as=object_detail.ObjectTextPanel.RenderOptions.JSON,
|
|
195
|
+
),
|
|
196
|
+
),
|
|
197
|
+
extra_tabs=(
|
|
198
|
+
object_detail.DistinctViewTab(
|
|
199
|
+
weight=900,
|
|
200
|
+
tab_id="networks",
|
|
201
|
+
label="Cloud Networks",
|
|
202
|
+
url_name="cloud:cloudresourcetype_networks",
|
|
203
|
+
related_object_attribute="cloud_networks",
|
|
204
|
+
panels=(
|
|
205
|
+
object_detail.ObjectsTablePanel(
|
|
206
|
+
section=SectionChoices.FULL_WIDTH,
|
|
207
|
+
weight=100,
|
|
208
|
+
table_class=CloudNetworkTable,
|
|
209
|
+
table_filter="cloud_resource_type",
|
|
210
|
+
tab_id="networks",
|
|
211
|
+
),
|
|
212
|
+
),
|
|
213
|
+
),
|
|
214
|
+
object_detail.DistinctViewTab(
|
|
215
|
+
weight=1000,
|
|
216
|
+
tab_id="services",
|
|
217
|
+
label="Cloud Services",
|
|
218
|
+
url_name="cloud:cloudresourcetype_services",
|
|
219
|
+
related_object_attribute="cloud_services",
|
|
220
|
+
panels=(
|
|
221
|
+
object_detail.ObjectsTablePanel(
|
|
222
|
+
section=SectionChoices.FULL_WIDTH,
|
|
223
|
+
weight=100,
|
|
224
|
+
table_class=CloudServiceTable,
|
|
225
|
+
table_filter="cloud_resource_type",
|
|
226
|
+
tab_id="services",
|
|
227
|
+
),
|
|
228
|
+
),
|
|
229
|
+
),
|
|
230
|
+
),
|
|
231
|
+
)
|
|
198
232
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
"networks_table": networks_table,
|
|
203
|
-
"services_count": services.count(),
|
|
204
|
-
"services_table": services_table,
|
|
205
|
-
}
|
|
206
|
-
)
|
|
233
|
+
@action(detail=True, url_path="networks")
|
|
234
|
+
def networks(self, request, *args, **kwargs):
|
|
235
|
+
return Response({})
|
|
207
236
|
|
|
208
|
-
|
|
237
|
+
@action(detail=True, url_path="services")
|
|
238
|
+
def services(self, request, *args, **kwargs):
|
|
239
|
+
return Response({})
|
|
209
240
|
|
|
210
241
|
|
|
211
242
|
class CloudServiceUIViewSet(NautobotUIViewSet):
|
|
@@ -76,6 +76,7 @@ class NautobotScheduleEntry(ModelEntry):
|
|
|
76
76
|
self._disable(model)
|
|
77
77
|
|
|
78
78
|
if isinstance(model.celery_kwargs, Mapping):
|
|
79
|
+
# TODO: this allows model.celery_kwargs to override keys like `nautobot_job_user_id`; is that desirable?
|
|
79
80
|
self.options.update(model.celery_kwargs)
|
|
80
81
|
|
|
81
82
|
# copy-paste from django_celery_beat.schedulers
|
nautobot/core/filters.py
CHANGED
|
@@ -397,7 +397,7 @@ class MappedPredicatesFilterMixin:
|
|
|
397
397
|
lookup_expr = lookup_info.get("lookup_expr")
|
|
398
398
|
preprocessor = lookup_info.get("preprocessor")
|
|
399
399
|
if not callable(preprocessor):
|
|
400
|
-
raise TypeError("Preprocessor {preprocessor} must be callable!")
|
|
400
|
+
raise TypeError(f"Preprocessor {preprocessor} must be callable!")
|
|
401
401
|
else:
|
|
402
402
|
raise TypeError(f"Predicate value must be a str or a dict! Got: {type(lookup_info)}")
|
|
403
403
|
|
nautobot/core/graphql/schema.py
CHANGED
|
@@ -95,6 +95,7 @@ CUSTOM_FIELD_MAPPING = {
|
|
|
95
95
|
CustomFieldTypeChoices.TYPE_URL: graphene.String(),
|
|
96
96
|
CustomFieldTypeChoices.TYPE_SELECT: graphene.String(),
|
|
97
97
|
CustomFieldTypeChoices.TYPE_JSON: JSON(),
|
|
98
|
+
CustomFieldTypeChoices.TYPE_MULTISELECT: graphene.List(graphene.String),
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
|
nautobot/core/jobs/__init__.py
CHANGED
|
@@ -38,7 +38,7 @@ from nautobot.extras.jobs import (
|
|
|
38
38
|
StringVar,
|
|
39
39
|
TextVar,
|
|
40
40
|
)
|
|
41
|
-
from nautobot.extras.models import ExportTemplate, GitRepository
|
|
41
|
+
from nautobot.extras.models import ExportTemplate, GitRepository, SavedView
|
|
42
42
|
|
|
43
43
|
name = "System Jobs"
|
|
44
44
|
|
|
@@ -150,6 +150,16 @@ class ExportObjectList(Job):
|
|
|
150
150
|
soft_time_limit = 1800
|
|
151
151
|
time_limit = 2000
|
|
152
152
|
|
|
153
|
+
def _get_saved_view_filter_params(self, query_params):
|
|
154
|
+
"""Extract filter params from saved view if applicable."""
|
|
155
|
+
if "saved_view" in query_params and "all_filters_removed" not in query_params:
|
|
156
|
+
saved_view_filters = SavedView.objects.get(pk=query_params["saved_view"]).config.get("filter_params", {})
|
|
157
|
+
if len(query_params) > 1:
|
|
158
|
+
# Retain only filters also present in query_params
|
|
159
|
+
saved_view_filters = {key: value for key, value in saved_view_filters.items() if key in query_params}
|
|
160
|
+
return saved_view_filters
|
|
161
|
+
return {}
|
|
162
|
+
|
|
153
163
|
def run(self, *, content_type, query_string="", export_format="csv", export_template=None): # pylint:disable=arguments-differ
|
|
154
164
|
if not self.user.has_perm(f"{content_type.app_label}.view_{content_type.model}"):
|
|
155
165
|
self.logger.error('User "%s" does not have permission to view %s objects', self.user, content_type.model)
|
|
@@ -178,8 +188,9 @@ class ExportObjectList(Job):
|
|
|
178
188
|
"sort",
|
|
179
189
|
"table_changes_pending",
|
|
180
190
|
)
|
|
181
|
-
filter_params =
|
|
182
|
-
|
|
191
|
+
filter_params = self._get_saved_view_filter_params(query_params)
|
|
192
|
+
filter_params.update(
|
|
193
|
+
get_filterable_params_from_filter_params(query_params, default_non_filter_params, filterset_class())
|
|
183
194
|
)
|
|
184
195
|
self.logger.debug("Filterset params: `%s`", filter_params)
|
|
185
196
|
filterset = filterset_class(filter_params, queryset)
|
nautobot/core/tables.py
CHANGED
|
@@ -704,11 +704,17 @@ class RelationshipColumn(django_tables2.Column):
|
|
|
704
704
|
if len(value) < 1:
|
|
705
705
|
return "—"
|
|
706
706
|
|
|
707
|
+
v = value[0]
|
|
708
|
+
peer = v.get_peer(record)
|
|
709
|
+
|
|
707
710
|
# Handle Relationships on the many side.
|
|
708
711
|
if self.relationship.has_many(self.peer_side):
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
+
if peer is not None:
|
|
713
|
+
meta = type(peer)._meta
|
|
714
|
+
name = meta.verbose_name_plural if len(value) > 1 else meta.verbose_name
|
|
715
|
+
else: # Perhaps a relationship to an uninstalled App's models?
|
|
716
|
+
peer_type = getattr(self.relationship, f"{self.peer_side}_type")
|
|
717
|
+
name = f"{peer_type} object(s)"
|
|
712
718
|
return format_html(
|
|
713
719
|
'<a href="{}?relationship={}&{}_id={}">{} {}</a>',
|
|
714
720
|
reverse("extras:relationshipassociation_list"),
|
|
@@ -720,6 +726,7 @@ class RelationshipColumn(django_tables2.Column):
|
|
|
720
726
|
)
|
|
721
727
|
# Handle Relationships on the one side.
|
|
722
728
|
else:
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
729
|
+
if peer is not None:
|
|
730
|
+
return format_html('<a href="{}">{}</a>', peer.get_absolute_url(), peer)
|
|
731
|
+
else:
|
|
732
|
+
return format_html("(unknown)")
|
nautobot/core/testing/views.py
CHANGED
|
@@ -302,6 +302,11 @@ class ViewTestCases:
|
|
|
302
302
|
slug_source = None
|
|
303
303
|
slugify_function = staticmethod(slugify)
|
|
304
304
|
slug_test_object = ""
|
|
305
|
+
expected_create_form_buttons = [
|
|
306
|
+
'<button type="submit" name="_create" class="btn btn-primary">Create</button>',
|
|
307
|
+
'<button type="submit" name="_addanother" class="btn btn-primary">Create and Add Another</button>',
|
|
308
|
+
]
|
|
309
|
+
expected_edit_form_buttons = ['<button type="submit" name="_update" class="btn btn-primary">Update</button>']
|
|
305
310
|
|
|
306
311
|
def test_create_object_without_permission(self):
|
|
307
312
|
# Try GET without permission
|
|
@@ -325,7 +330,14 @@ class ViewTestCases:
|
|
|
325
330
|
self.add_permissions(f"{self.model._meta.app_label}.add_{self.model._meta.model_name}")
|
|
326
331
|
|
|
327
332
|
# Try GET with model-level permission
|
|
328
|
-
self.
|
|
333
|
+
response = self.client.get(self._get_url("add"))
|
|
334
|
+
self.assertHttpStatus(response, 200)
|
|
335
|
+
# The response content should contain the expected form buttons
|
|
336
|
+
for button in self.expected_create_form_buttons:
|
|
337
|
+
self.assertBodyContains(response, button)
|
|
338
|
+
# The response content should not contain the expected form buttons
|
|
339
|
+
for button in self.expected_edit_form_buttons:
|
|
340
|
+
self.assertNotContains(response, button)
|
|
329
341
|
|
|
330
342
|
# Try POST with model-level permission
|
|
331
343
|
request = {
|
|
@@ -439,6 +451,11 @@ class ViewTestCases:
|
|
|
439
451
|
|
|
440
452
|
form_data = {}
|
|
441
453
|
update_data = {}
|
|
454
|
+
expected_edit_form_buttons = ['<button type="submit" name="_update" class="btn btn-primary">Update</button>']
|
|
455
|
+
expected_create_form_buttons = [
|
|
456
|
+
'<button type="submit" name="_create" class="btn btn-primary">Create</button>',
|
|
457
|
+
'<button type="submit" name="_addanother" class="btn btn-primary">Create and Add Another</button>',
|
|
458
|
+
]
|
|
442
459
|
|
|
443
460
|
def test_edit_object_without_permission(self):
|
|
444
461
|
instance = self._get_queryset().first()
|
|
@@ -464,7 +481,15 @@ class ViewTestCases:
|
|
|
464
481
|
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
465
482
|
|
|
466
483
|
# Try GET with model-level permission
|
|
467
|
-
self.
|
|
484
|
+
response = self.client.get(self._get_url("edit", instance))
|
|
485
|
+
self.assertHttpStatus(response, 200)
|
|
486
|
+
# The response content should contain the expected form buttons
|
|
487
|
+
for button in self.expected_edit_form_buttons:
|
|
488
|
+
self.assertBodyContains(response, button)
|
|
489
|
+
|
|
490
|
+
# The response content should not contain the unexpected form buttons
|
|
491
|
+
for button in self.expected_create_form_buttons:
|
|
492
|
+
self.assertNotContains(response, button)
|
|
468
493
|
|
|
469
494
|
# Try POST with model-level permission
|
|
470
495
|
update_data = self.update_data or self.form_data
|
nautobot/core/tests/test_jobs.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import codecs
|
|
2
|
+
import csv
|
|
2
3
|
from datetime import timedelta
|
|
4
|
+
from io import StringIO
|
|
3
5
|
import json
|
|
4
6
|
from pathlib import Path
|
|
5
7
|
|
|
@@ -10,6 +12,7 @@ from django.utils import timezone
|
|
|
10
12
|
import yaml
|
|
11
13
|
|
|
12
14
|
from nautobot.circuits.models import Circuit, CircuitType, Provider
|
|
15
|
+
from nautobot.core.jobs import ExportObjectList
|
|
13
16
|
from nautobot.core.jobs.cleanup import CleanupTypes
|
|
14
17
|
from nautobot.core.testing import create_job_result_and_run_job, TransactionTestCase
|
|
15
18
|
from nautobot.core.testing.context import load_event_broker_override_settings
|
|
@@ -25,6 +28,7 @@ from nautobot.extras.models import (
|
|
|
25
28
|
JobResult,
|
|
26
29
|
ObjectChange,
|
|
27
30
|
Role,
|
|
31
|
+
SavedView,
|
|
28
32
|
Status,
|
|
29
33
|
Tag,
|
|
30
34
|
)
|
|
@@ -40,6 +44,32 @@ class ExportObjectListTest(TransactionTestCase):
|
|
|
40
44
|
|
|
41
45
|
databases = ("default", "job_logs")
|
|
42
46
|
|
|
47
|
+
def _create_saved_view(self, model_class=Status, config=None):
|
|
48
|
+
"""Helper to create a SavedView with optional filter config."""
|
|
49
|
+
return SavedView.objects.create(
|
|
50
|
+
name="Global default View",
|
|
51
|
+
owner=self.user,
|
|
52
|
+
view=f"{model_class._meta.app_label}:{model_class._meta.model_name}_list",
|
|
53
|
+
is_global_default=True,
|
|
54
|
+
config=config or {},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def _run_export_job(self, query_string, model_class=Status):
|
|
58
|
+
"""Helper to run export job and return parsed CSV rows."""
|
|
59
|
+
job_result = create_job_result_and_run_job(
|
|
60
|
+
"nautobot.core.jobs",
|
|
61
|
+
"ExportObjectList",
|
|
62
|
+
content_type=ContentType.objects.get_for_model(model_class).pk,
|
|
63
|
+
query_string=query_string,
|
|
64
|
+
)
|
|
65
|
+
self.assertJobResultStatus(job_result)
|
|
66
|
+
self.assertTrue(job_result.files.exists())
|
|
67
|
+
self.assertEqual(
|
|
68
|
+
Path(job_result.files.first().file.name).name, f"nautobot_{model_class._meta.verbose_name_plural}.csv"
|
|
69
|
+
)
|
|
70
|
+
csv_data = job_result.files.first().file.read().decode("utf-8").lstrip("\ufeff")
|
|
71
|
+
return list(csv.DictReader(StringIO(csv_data)))
|
|
72
|
+
|
|
43
73
|
def test_export_without_permission(self):
|
|
44
74
|
"""Job should enforce user permissions on the content-type being asked for export."""
|
|
45
75
|
job_result = create_job_result_and_run_job(
|
|
@@ -136,6 +166,89 @@ class ExportObjectListTest(TransactionTestCase):
|
|
|
136
166
|
data = yaml.safe_load(yaml_data)
|
|
137
167
|
self.assertEqual(data["manufacturer"], "Cisco")
|
|
138
168
|
|
|
169
|
+
def test_get_saved_view_filter_params(self):
|
|
170
|
+
"""Test various cases for the saved view filter parameters."""
|
|
171
|
+
saved_view = self._create_saved_view(config={"filter_params": {"name": ["Active"]}})
|
|
172
|
+
test_cases = [
|
|
173
|
+
# (query_params, expected_output)
|
|
174
|
+
({"saved_view": saved_view.pk}, {"name": ["Active"]}),
|
|
175
|
+
(
|
|
176
|
+
{
|
|
177
|
+
"saved_view": saved_view.pk,
|
|
178
|
+
"name": ["Active"],
|
|
179
|
+
"content_types": ["dcim.devices"],
|
|
180
|
+
}, # new filter content_types
|
|
181
|
+
{"name": ["Active"]},
|
|
182
|
+
),
|
|
183
|
+
(
|
|
184
|
+
{"saved_view": saved_view.pk, "content_types": ["dcim.devices"]}, # name filter was deleted
|
|
185
|
+
{},
|
|
186
|
+
),
|
|
187
|
+
({"saved_view": saved_view.pk, "all_filters_removed": "true"}, {}),
|
|
188
|
+
(
|
|
189
|
+
{"name": ["Active"]}, # No saved view provided
|
|
190
|
+
{},
|
|
191
|
+
),
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
for query_params, expected_output in test_cases:
|
|
195
|
+
with self.subTest(query_params=query_params, expected_output=expected_output):
|
|
196
|
+
job = ExportObjectList()
|
|
197
|
+
filter_params = job._get_saved_view_filter_params(query_params)
|
|
198
|
+
self.assertEqual(filter_params, expected_output)
|
|
199
|
+
|
|
200
|
+
def test_export_saved_view_to_csv_without_filters(self):
|
|
201
|
+
"""Export a SavedView to CSV without any filters applied."""
|
|
202
|
+
# URL: /?saved_view=<id>
|
|
203
|
+
sv = self._create_saved_view()
|
|
204
|
+
rows = self._run_export_job(query_string=f"saved_view={sv.pk}")
|
|
205
|
+
self.assertEqual(len(rows), Status.objects.count())
|
|
206
|
+
|
|
207
|
+
def test_export_saved_view_to_csv_with_filters_from_saved_view(self):
|
|
208
|
+
"""Export a SavedView to CSV using filters defined in the SavedView config."""
|
|
209
|
+
# URL: /?saved_view=<id>
|
|
210
|
+
filter_name = Status.objects.first().name
|
|
211
|
+
sv = self._create_saved_view(config={"filter_params": {"name": [filter_name]}})
|
|
212
|
+
rows = self._run_export_job(query_string=f"saved_view={sv.pk}")
|
|
213
|
+
self.assertGreaterEqual(Status.objects.count(), 1) # Ensure multiple Statuses exist and filter works
|
|
214
|
+
self.assertEqual(len(rows), 1)
|
|
215
|
+
self.assertEqual(rows[0]["name"], filter_name)
|
|
216
|
+
|
|
217
|
+
def test_export_saved_view_to_csv_with_combined_filters(self):
|
|
218
|
+
"""Export a SavedView to CSV using combined filters from SavedView config and query params."""
|
|
219
|
+
# URL: /?saved_view=<id>&name=<filter_name>&name=<filter_name2>
|
|
220
|
+
filter_name = Status.objects.first().name
|
|
221
|
+
filter_name2 = Status.objects.last().name
|
|
222
|
+
sv = self._create_saved_view(config={"filter_params": {"name": [filter_name]}})
|
|
223
|
+
rows = self._run_export_job(query_string=f"saved_view={sv.pk}&name={filter_name}&name={filter_name2}")
|
|
224
|
+
self.assertEqual(len(rows), 2)
|
|
225
|
+
self.assertEqual(rows[0]["name"], filter_name)
|
|
226
|
+
self.assertEqual(rows[1]["name"], filter_name2)
|
|
227
|
+
|
|
228
|
+
def test_export_saved_view_manufacturer_to_csv_with_replaced_filters(self):
|
|
229
|
+
"""Export a SavedView manufacturer to CSV after replacing filters."""
|
|
230
|
+
# URL: /?saved_view=<id>&description=<manufacturer2>
|
|
231
|
+
manufacturer = Manufacturer.objects.create(name="Test Manufacturer")
|
|
232
|
+
manufacturer2 = Manufacturer.objects.create(name="Test2 Manufacturer", description="test filter")
|
|
233
|
+
filter_name = manufacturer.name
|
|
234
|
+
filter_description = manufacturer2.description
|
|
235
|
+
sv = self._create_saved_view(model_class=Manufacturer, config={"filter_params": {"name": [filter_name]}})
|
|
236
|
+
rows = self._run_export_job(
|
|
237
|
+
query_string=f"saved_view={sv.pk}&description={filter_description}", model_class=Manufacturer
|
|
238
|
+
)
|
|
239
|
+
self.assertEqual(len(rows), 1)
|
|
240
|
+
self.assertEqual(rows[0]["name"], manufacturer2.name)
|
|
241
|
+
self.assertEqual(rows[0]["description"], filter_description)
|
|
242
|
+
self.assertTrue(all(row["name"] != filter_name for row in rows))
|
|
243
|
+
|
|
244
|
+
def test_export_saved_view_to_csv_after_removing_all_filters(self):
|
|
245
|
+
"""Export a SavedView to CSV after removing all filters."""
|
|
246
|
+
# URL: /?saved_view=<id>&all_filters_removed=true
|
|
247
|
+
filter_name = Status.objects.first().name
|
|
248
|
+
sv = self._create_saved_view(config={"filter_params": {"name": [filter_name]}})
|
|
249
|
+
rows = self._run_export_job(query_string=f"saved_view={sv.pk}&all_filters_removed=true")
|
|
250
|
+
self.assertEqual(len(rows), Status.objects.count())
|
|
251
|
+
|
|
139
252
|
|
|
140
253
|
class ImportObjectsTestCase(TransactionTestCase):
|
|
141
254
|
databases = ("default", "job_logs")
|