nautobot 2.4.1__py3-none-any.whl → 2.4.3__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/inc/circuit_termination.html +1 -1
- nautobot/circuits/tests/integration/test_circuit.py +135 -0
- nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +43 -0
- nautobot/circuits/tests/integration/test_relationships.py +1 -1
- nautobot/circuits/views.py +4 -1
- nautobot/cloud/api/views.py +3 -3
- nautobot/core/apps/__init__.py +0 -5
- nautobot/core/constants.py +0 -1
- nautobot/core/forms/__init__.py +2 -0
- nautobot/core/forms/forms.py +2 -1
- nautobot/core/forms/widgets.py +8 -0
- nautobot/core/management/commands/generate_performance_test_endpoints.py +268 -0
- nautobot/core/templates/generic/object_bulk_delete.html +1 -1
- nautobot/core/templates/generic/object_bulk_destroy.html +1 -1
- nautobot/core/templates/generic/object_bulk_edit.html +1 -1
- nautobot/core/templates/generic/object_bulk_import.html +1 -1
- nautobot/core/templates/generic/object_create.html +5 -0
- nautobot/core/templates/generic/object_delete.html +1 -1
- nautobot/core/templates/generic/object_detail.html +1 -1
- nautobot/core/templates/generic/object_edit.html +1 -1
- nautobot/core/templates/inc/javascript.html +2 -0
- nautobot/core/templates/widgets/clearable_file.html +5 -0
- nautobot/core/templatetags/helpers.py +3 -3
- nautobot/core/testing/integration.py +469 -12
- nautobot/core/tests/test_commands.py +31 -0
- nautobot/core/tests/test_jobs.py +34 -2
- nautobot/core/tests/test_utils.py +17 -2
- nautobot/core/utils/git.py +7 -2
- nautobot/core/utils/lookup.py +12 -1
- nautobot/core/views/generic.py +10 -2
- nautobot/core/views/mixins.py +22 -7
- nautobot/core/views/utils.py +2 -2
- nautobot/dcim/api/views.py +11 -10
- nautobot/dcim/forms.py +15 -6
- nautobot/dcim/models/devices.py +1 -2
- nautobot/dcim/tables/devices.py +2 -1
- nautobot/dcim/templates/dcim/cable.html +1 -1
- nautobot/dcim/templates/dcim/cable_trace.html +4 -4
- nautobot/dcim/templates/dcim/consoleport.html +14 -4
- nautobot/dcim/templates/dcim/consoleserverport.html +14 -4
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +3 -3
- nautobot/dcim/templates/dcim/device.html +2 -2
- nautobot/dcim/templates/dcim/device_component.html +1 -1
- nautobot/dcim/templates/dcim/devicetype.html +1 -1
- nautobot/dcim/templates/dcim/frontport.html +7 -2
- nautobot/dcim/templates/dcim/interface.html +9 -4
- nautobot/dcim/templates/dcim/location.html +1 -1
- nautobot/dcim/templates/dcim/locationtype.html +1 -1
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/manufacturer.html +1 -1
- nautobot/dcim/templates/dcim/platform.html +1 -1
- nautobot/dcim/templates/dcim/powerfeed.html +9 -4
- nautobot/dcim/templates/dcim/poweroutlet.html +14 -4
- nautobot/dcim/templates/dcim/powerpanel.html +1 -1
- nautobot/dcim/templates/dcim/powerport.html +14 -4
- nautobot/dcim/templates/dcim/rack.html +1 -1
- nautobot/dcim/templates/dcim/rackgroup.html +1 -1
- nautobot/dcim/templates/dcim/rackreservation.html +2 -2
- nautobot/dcim/templates/dcim/rearport.html +7 -2
- nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +30 -0
- nautobot/dcim/tests/integration/test_fileinputpicker.py +87 -0
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +43 -0
- nautobot/dcim/tests/test_models.py +1 -1
- nautobot/dcim/tests/test_views.py +9 -1
- nautobot/dcim/views.py +12 -15
- nautobot/extras/api/serializers.py +33 -0
- nautobot/extras/api/views.py +13 -5
- nautobot/extras/constants.py +1 -0
- nautobot/extras/datasources/git.py +125 -0
- nautobot/extras/forms/forms.py +4 -0
- nautobot/extras/jobs.py +8 -1
- nautobot/extras/migrations/0122_add_graphqlquery_owner_content_type.py +34 -0
- nautobot/extras/models/customfields.py +29 -12
- nautobot/extras/models/datasources.py +85 -0
- nautobot/extras/models/models.py +15 -0
- nautobot/extras/models/relationships.py +17 -5
- nautobot/extras/signals.py +15 -1
- nautobot/extras/templates/extras/computedfield.html +1 -1
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema.html +1 -1
- nautobot/extras/templates/extras/customfield.html +1 -1
- nautobot/extras/templates/extras/customlink.html +1 -1
- nautobot/extras/templates/extras/dynamicgroup.html +1 -1
- nautobot/extras/templates/extras/exporttemplate.html +1 -1
- nautobot/extras/templates/extras/gitrepository.html +1 -1
- nautobot/extras/templates/extras/graphqlquery.html +1 -1
- nautobot/extras/templates/extras/job.html +1 -0
- nautobot/extras/templates/extras/job_detail.html +1 -1
- nautobot/extras/templates/extras/jobbutton_retrieve.html +1 -1
- nautobot/extras/templates/extras/jobhook.html +1 -1
- nautobot/extras/templates/extras/jobresult.html +1 -1
- nautobot/extras/templates/extras/objectchange.html +1 -1
- nautobot/extras/templates/extras/plugin_detail.html +1 -1
- nautobot/extras/templates/extras/relationship.html +1 -63
- nautobot/extras/templates/extras/role_retrieve.html +1 -1
- nautobot/extras/templates/extras/scheduledjob.html +1 -1
- nautobot/extras/templates/extras/secret.html +1 -1
- nautobot/extras/templates/extras/secretsgroup.html +1 -1
- nautobot/extras/templates/extras/status.html +1 -1
- nautobot/extras/templates/extras/tag.html +1 -1
- nautobot/extras/templates/extras/webhook.html +1 -1
- nautobot/extras/tests/git_data/01-valid-files/graphql_queries/device_interfaces.gql +8 -0
- nautobot/extras/tests/git_data/01-valid-files/graphql_queries/device_names.gql +5 -0
- nautobot/extras/tests/git_data/02-invalid-files/graphql_queries/bad_device_names.gql +5 -0
- nautobot/extras/tests/git_helper.py +9 -1
- nautobot/extras/tests/integration/__init__.py +29 -16
- nautobot/extras/tests/test_api.py +6 -0
- nautobot/extras/tests/test_customfields.py +49 -51
- nautobot/extras/tests/test_datasources.py +27 -0
- nautobot/extras/tests/test_dynamicgroups.py +14 -0
- nautobot/extras/tests/test_models.py +283 -0
- nautobot/extras/tests/test_utils.py +22 -1
- nautobot/extras/tests/test_views.py +197 -9
- nautobot/extras/utils.py +47 -8
- nautobot/extras/views.py +84 -26
- nautobot/ipam/api/views.py +3 -3
- nautobot/ipam/forms.py +2 -6
- nautobot/ipam/models.py +8 -2
- nautobot/ipam/tables.py +2 -2
- nautobot/ipam/templates/ipam/ipaddress.html +1 -1
- nautobot/ipam/templates/ipam/prefix.html +1 -1
- nautobot/ipam/templates/ipam/rir.html +1 -1
- nautobot/ipam/templates/ipam/routetarget.html +1 -1
- nautobot/ipam/templates/ipam/service.html +1 -1
- nautobot/ipam/templates/ipam/vlan.html +1 -1
- nautobot/ipam/templates/ipam/vlangroup.html +1 -1
- nautobot/ipam/templates/ipam/vrf.html +1 -1
- nautobot/ipam/tests/test_models.py +24 -0
- nautobot/ipam/tests/test_utils.py +41 -2
- nautobot/ipam/utils/__init__.py +18 -11
- nautobot/project-static/bootstrap-filestyle-1.2.3/bootstrap-filestyle.min.js +11 -0
- nautobot/project-static/docs/404.html +87 -12
- nautobot/project-static/docs/apps/index.html +88 -13
- nautobot/project-static/docs/apps/nautobot-apps.html +88 -13
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.60a45f97.min.js} +1 -1
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.60a45f97.min.js.map} +1 -1
- nautobot/project-static/docs/assets/javascripts/workers/{search.6ce7567c.min.js → search.f8cc74c7.min.js} +1 -1
- nautobot/project-static/docs/assets/javascripts/workers/{search.6ce7567c.min.js.map → search.f8cc74c7.min.js.map} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.6f8fc17f.min.css → main.a40c8224.min.css} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +87 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +177 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +114 -17
- nautobot/project-static/docs/development/apps/api/configuration-view.html +87 -12
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +87 -12
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +87 -12
- nautobot/project-static/docs/development/apps/api/models/global-search.html +87 -12
- nautobot/project-static/docs/development/apps/api/models/graphql.html +96 -21
- nautobot/project-static/docs/development/apps/api/models/index.html +87 -12
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +89 -14
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +87 -12
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +87 -12
- nautobot/project-static/docs/development/apps/api/prometheus.html +87 -12
- nautobot/project-static/docs/development/apps/api/setup.html +88 -13
- nautobot/project-static/docs/development/apps/api/testing.html +87 -12
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +87 -12
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +87 -12
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +87 -12
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +87 -12
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/base-template.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/index.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/notes.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +87 -12
- nautobot/project-static/docs/development/apps/api/views/urls.html +87 -12
- nautobot/project-static/docs/development/apps/index.html +87 -12
- nautobot/project-static/docs/development/apps/migration/code-updates.html +93 -17
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +89 -14
- nautobot/project-static/docs/development/apps/migration/from-v1.html +90 -15
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +87 -12
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +87 -12
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +87 -12
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +87 -12
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +87 -12
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +87 -12
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +88 -13
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +87 -12
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +87 -12
- nautobot/project-static/docs/development/core/application-registry.html +87 -12
- nautobot/project-static/docs/development/core/best-practices.html +88 -13
- nautobot/project-static/docs/development/core/bootstrap-ui.html +88 -13
- nautobot/project-static/docs/development/core/caching.html +87 -12
- nautobot/project-static/docs/development/core/controllers.html +87 -12
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +94 -19
- nautobot/project-static/docs/development/core/generic-views.html +87 -12
- nautobot/project-static/docs/development/core/getting-started.html +89 -14
- nautobot/project-static/docs/development/core/homepage.html +87 -12
- nautobot/project-static/docs/development/core/index.html +88 -13
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +90 -15
- nautobot/project-static/docs/development/core/model-checklist.html +88 -13
- nautobot/project-static/docs/development/core/model-features.html +87 -12
- nautobot/project-static/docs/development/core/natural-keys.html +87 -12
- nautobot/project-static/docs/development/core/navigation-menu.html +88 -13
- nautobot/project-static/docs/development/core/release-checklist.html +88 -13
- nautobot/project-static/docs/development/core/role-internals.html +87 -12
- nautobot/project-static/docs/development/core/settings.html +88 -13
- nautobot/project-static/docs/development/core/style-guide.html +91 -16
- nautobot/project-static/docs/development/core/templates.html +88 -13
- nautobot/project-static/docs/development/core/testing.html +87 -12
- nautobot/project-static/docs/development/core/ui-component-framework.html +87 -12
- nautobot/project-static/docs/development/core/user-preferences.html +87 -12
- nautobot/project-static/docs/development/index.html +87 -12
- nautobot/project-static/docs/development/jobs/index.html +95 -13
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +90 -14
- nautobot/project-static/docs/index.html +90 -14
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +89 -14
- nautobot/project-static/docs/overview/design_philosophy.html +87 -12
- nautobot/project-static/docs/release-notes/index.html +87 -12
- nautobot/project-static/docs/release-notes/version-1.0.html +89 -14
- nautobot/project-static/docs/release-notes/version-1.1.html +89 -14
- nautobot/project-static/docs/release-notes/version-1.2.html +90 -15
- nautobot/project-static/docs/release-notes/version-1.3.html +88 -13
- nautobot/project-static/docs/release-notes/version-1.4.html +104 -29
- nautobot/project-static/docs/release-notes/version-1.5.html +95 -20
- nautobot/project-static/docs/release-notes/version-1.6.html +91 -16
- nautobot/project-static/docs/release-notes/version-2.0.html +97 -22
- nautobot/project-static/docs/release-notes/version-2.1.html +94 -19
- nautobot/project-static/docs/release-notes/version-2.2.html +88 -13
- nautobot/project-static/docs/release-notes/version-2.3.html +91 -16
- nautobot/project-static/docs/release-notes/version-2.4.html +465 -12
- nautobot/project-static/docs/requirements.txt +1 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +296 -288
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +90 -15
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +87 -12
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +91 -16
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +87 -12
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +88 -13
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +90 -15
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +87 -12
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +95 -20
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +90 -15
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +88 -13
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +87 -12
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +91 -16
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +87 -12
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +102 -27
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +89 -14
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +87 -12
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +88 -13
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +87 -12
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +87 -12
- nautobot/project-static/docs/user-guide/administration/installation/index.html +87 -12
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +88 -13
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +93 -18
- nautobot/project-static/docs/user-guide/administration/installation/services.html +88 -13
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +87 -12
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +87 -12
- nautobot/project-static/docs/user-guide/administration/security/index.html +9420 -0
- nautobot/project-static/docs/user-guide/administration/security/notices.html +9844 -0
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +87 -12
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +88 -13
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +87 -12
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +98 -20
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +87 -12
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +99 -24
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +90 -15
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +188 -30
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +87 -12
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +87 -12
- nautobot/project-static/docs/user-guide/index.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +88 -13
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +407 -14
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +90 -15
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +89 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +93 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +87 -12
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +87 -12
- nautobot/project-static/js/dropdown.js +28 -0
- nautobot/tenancy/forms.py +9 -0
- nautobot/tenancy/templates/tenancy/tenant.html +1 -2
- nautobot/tenancy/templates/tenancy/tenant_create.html +21 -0
- nautobot/tenancy/templates/tenancy/tenant_edit.html +2 -21
- nautobot/tenancy/templates/tenancy/tenantgroup.html +2 -44
- nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +1 -0
- nautobot/tenancy/tests/test_views.py +5 -1
- nautobot/tenancy/urls.py +7 -79
- nautobot/tenancy/views.py +51 -80
- nautobot/virtualization/templates/virtualization/cluster.html +1 -1
- nautobot/virtualization/templates/virtualization/clustergroup.html +1 -1
- nautobot/virtualization/templates/virtualization/clustertype.html +1 -1
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
- nautobot/virtualization/templates/virtualization/vminterface.html +1 -1
- nautobot/wireless/api/serializers.py +6 -1
- nautobot/wireless/api/views.py +3 -3
- nautobot/wireless/tests/test_api.py +5 -0
- {nautobot-2.4.1.dist-info → nautobot-2.4.3.dist-info}/METADATA +12 -12
- {nautobot-2.4.1.dist-info → nautobot-2.4.3.dist-info}/RECORD +459 -443
- nautobot/dcim/tests/integration/test_device_bulk_delete.py +0 -189
- nautobot/dcim/tests/integration/test_device_bulk_edit.py +0 -181
- /nautobot/project-static/docs/assets/stylesheets/{main.6f8fc17f.min.css.map → main.a40c8224.min.css.map} +0 -0
- {nautobot-2.4.1.dist-info → nautobot-2.4.3.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.1.dist-info → nautobot-2.4.3.dist-info}/NOTICE +0 -0
- {nautobot-2.4.1.dist-info → nautobot-2.4.3.dist-info}/WHEEL +0 -0
- {nautobot-2.4.1.dist-info → nautobot-2.4.3.dist-info}/entry_points.txt +0 -0
nautobot/core/tests/test_jobs.py
CHANGED
|
@@ -750,16 +750,48 @@ class BulkEditTestCase(TransactionTestCase):
|
|
|
750
750
|
description="Example description for bulk edit",
|
|
751
751
|
)
|
|
752
752
|
|
|
753
|
-
# Assert Namespaces
|
|
753
|
+
# Assert Namespaces within pk_list get updated tags
|
|
754
754
|
for namespace in namespaces[:3]:
|
|
755
755
|
self.assertTrue(namespace.tags.filter(pk__in=[tag.pk for tag in self.tags[:3]]).exists())
|
|
756
756
|
self.assertFalse(namespace.tags.filter(pk__in=[tag.pk for tag in self.tags[3:]]).exists())
|
|
757
757
|
|
|
758
|
-
# Assert Namespaces not
|
|
758
|
+
# Assert Namespaces not within pk_list did not get updated tags
|
|
759
759
|
for namespace in namespaces[3:]:
|
|
760
760
|
self.assertFalse(namespace.tags.filter(pk__in=[tag.pk for tag in self.tags[:3]]).exists())
|
|
761
761
|
self.assertTrue(namespace.tags.filter(pk__in=[tag.pk for tag in self.tags[3:]]).exists())
|
|
762
762
|
|
|
763
|
+
job_result = create_job_result_and_run_job(
|
|
764
|
+
"nautobot.core.jobs.bulk_actions",
|
|
765
|
+
"BulkEditObjects",
|
|
766
|
+
content_type=self.namespace_ct.id,
|
|
767
|
+
edit_all=False,
|
|
768
|
+
filter_query_params={},
|
|
769
|
+
form_data={
|
|
770
|
+
"pk": pk_list,
|
|
771
|
+
"description": "Example description for bulk edit",
|
|
772
|
+
"add_tags": [str(self.tags[0].id)],
|
|
773
|
+
"remove_tags": [str(self.tags[-1].id)],
|
|
774
|
+
},
|
|
775
|
+
username=self.user.username,
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
self._common_no_error_test_assertion(
|
|
779
|
+
Namespace,
|
|
780
|
+
job_result,
|
|
781
|
+
3,
|
|
782
|
+
description="Example description for bulk edit",
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
# Assert Namespaces within pk_list get updated tag
|
|
786
|
+
for namespace in namespaces[:3]:
|
|
787
|
+
self.assertTrue(namespace.tags.filter(pk__in=[self.tags[0].pk]).exists())
|
|
788
|
+
self.assertFalse(namespace.tags.filter(pk__in=[self.tags[-1].pk]).exists())
|
|
789
|
+
|
|
790
|
+
# Assert Namespaces not within pk_list did not get updated tag
|
|
791
|
+
for namespace in namespaces[3:]:
|
|
792
|
+
self.assertFalse(namespace.tags.filter(pk__in=[self.tags[0].pk]).exists())
|
|
793
|
+
self.assertTrue(namespace.tags.filter(pk__in=[self.tags[-1].pk]).exists())
|
|
794
|
+
|
|
763
795
|
def test_bulk_edit_objects_filter_all(self):
|
|
764
796
|
"""
|
|
765
797
|
Bulk edit all of the filtered Status instances.
|
|
@@ -273,10 +273,25 @@ class GetFooForModelTest(TestCase):
|
|
|
273
273
|
"""
|
|
274
274
|
Test that `get_model_for_view_name` returns the appropriate Model, if the colon separated view name provided.
|
|
275
275
|
"""
|
|
276
|
-
with self.subTest("Test core view."):
|
|
276
|
+
with self.subTest("Test core UI view."):
|
|
277
277
|
self.assertEqual(lookup.get_model_for_view_name("dcim:device_list"), dcim_models.Device)
|
|
278
|
-
|
|
278
|
+
self.assertEqual(lookup.get_model_for_view_name("dcim:device"), dcim_models.Device)
|
|
279
|
+
with self.subTest("Test app UI view."):
|
|
279
280
|
self.assertEqual(lookup.get_model_for_view_name("plugins:example_app:examplemodel_list"), ExampleModel)
|
|
281
|
+
self.assertEqual(lookup.get_model_for_view_name("plugins:example_app:examplemodel"), ExampleModel)
|
|
282
|
+
with self.subTest("Test core API view."):
|
|
283
|
+
self.assertEqual(lookup.get_model_for_view_name("dcim-api:device-list"), dcim_models.Device)
|
|
284
|
+
self.assertEqual(lookup.get_model_for_view_name("dcim-api:device-detail"), dcim_models.Device)
|
|
285
|
+
with self.subTest("Test app API view."):
|
|
286
|
+
self.assertEqual(
|
|
287
|
+
lookup.get_model_for_view_name("plugins-api:example_app-api:examplemodel-detail"), ExampleModel
|
|
288
|
+
)
|
|
289
|
+
self.assertEqual(
|
|
290
|
+
lookup.get_model_for_view_name("plugins-api:example_app-api:examplemodel-list"), ExampleModel
|
|
291
|
+
)
|
|
292
|
+
with self.subTest("Test unconventional model views."):
|
|
293
|
+
self.assertEqual(lookup.get_model_for_view_name("extras-api:contenttype-detail"), ContentType)
|
|
294
|
+
self.assertEqual(lookup.get_model_for_view_name("users-api:group-detail"), Group)
|
|
280
295
|
with self.subTest("Test unexpected view."):
|
|
281
296
|
with self.assertRaises(ValueError) as err:
|
|
282
297
|
lookup.get_model_for_view_name("unknown:plugins:example_app:examplemodel_list")
|
nautobot/core/utils/git.py
CHANGED
|
@@ -57,7 +57,7 @@ class BranchDoesNotExist(Exception):
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
class GitRepo:
|
|
60
|
-
def __init__(self, path, url, clone_initially=True):
|
|
60
|
+
def __init__(self, path, url, clone_initially=True, branch=None, depth=0):
|
|
61
61
|
"""
|
|
62
62
|
Ensure that we have a clone of the given remote Git repository URL at the given local directory path.
|
|
63
63
|
|
|
@@ -65,6 +65,8 @@ class GitRepo:
|
|
|
65
65
|
path (str): path to git repo
|
|
66
66
|
url (str): git repo url
|
|
67
67
|
clone_initially (bool): True if the repo needs to be cloned
|
|
68
|
+
branch (str): branch to checkout
|
|
69
|
+
depth (int): depth of the clone
|
|
68
70
|
"""
|
|
69
71
|
self.url = url
|
|
70
72
|
self.sanitized_url = sanitize(url)
|
|
@@ -73,7 +75,10 @@ class GitRepo:
|
|
|
73
75
|
elif clone_initially:
|
|
74
76
|
# Don't log `url` as it may include authentication details.
|
|
75
77
|
logger.debug("Cloning git repository to %s...", path)
|
|
76
|
-
|
|
78
|
+
if not depth:
|
|
79
|
+
self.repo = Repo.clone_from(url, to_path=path, env=GIT_ENVIRONMENT, branch=branch)
|
|
80
|
+
else:
|
|
81
|
+
self.repo = Repo.clone_from(url, to_path=path, env=GIT_ENVIRONMENT, branch=branch, depth=depth)
|
|
77
82
|
else:
|
|
78
83
|
self.repo = Repo.init(path)
|
|
79
84
|
self.repo.create_remote("origin", url=url)
|
nautobot/core/utils/lookup.py
CHANGED
|
@@ -250,6 +250,11 @@ def get_model_for_view_name(view_name):
|
|
|
250
250
|
Return the model class associated with the given view_name e.g. "circuits:circuit_detail", "dcim:device_list" and etc.
|
|
251
251
|
If the app_label or model_name contained by the given view_name is invalid, this will return `None`.
|
|
252
252
|
"""
|
|
253
|
+
if view_name == "users-api:group-detail":
|
|
254
|
+
return Group
|
|
255
|
+
if view_name == "extras-api:contenttype-detail":
|
|
256
|
+
return ContentType
|
|
257
|
+
|
|
253
258
|
split_view_name = view_name.split(":")
|
|
254
259
|
if len(split_view_name) == 2:
|
|
255
260
|
app_label, model_name = split_view_name # dcim, device_list
|
|
@@ -257,7 +262,13 @@ def get_model_for_view_name(view_name):
|
|
|
257
262
|
_, app_label, model_name = split_view_name # plugins, app_name, model_list
|
|
258
263
|
else:
|
|
259
264
|
raise ValueError(f"Unexpected View Name: {view_name}")
|
|
260
|
-
|
|
265
|
+
|
|
266
|
+
delimiter = "_"
|
|
267
|
+
if app_label.endswith("-api"):
|
|
268
|
+
app_label = app_label.replace("-api", "")
|
|
269
|
+
delimiter = "-"
|
|
270
|
+
|
|
271
|
+
model_name = model_name.split(delimiter)[0] # device
|
|
261
272
|
|
|
262
273
|
try:
|
|
263
274
|
model = apps.get_model(app_label=app_label, model_name=model_name)
|
nautobot/core/views/generic.py
CHANGED
|
@@ -214,8 +214,16 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
214
214
|
resolved_path = resolve(request.path)
|
|
215
215
|
list_url = f"{resolved_path.app_name}:{resolved_path.url_name}"
|
|
216
216
|
|
|
217
|
+
skip_user_and_global_default_saved_view = False
|
|
218
|
+
if self.filterset is not None:
|
|
219
|
+
skip_user_and_global_default_saved_view = get_filterable_params_from_filter_params(
|
|
220
|
+
request.GET.copy(),
|
|
221
|
+
self.non_filter_params,
|
|
222
|
+
self.filterset(),
|
|
223
|
+
)
|
|
224
|
+
|
|
217
225
|
# If the user clicks on the clear view button, we do not check for global or user defaults
|
|
218
|
-
if not clear_view and not request.GET.get("saved_view"):
|
|
226
|
+
if not skip_user_and_global_default_saved_view and not clear_view and not request.GET.get("saved_view"):
|
|
219
227
|
# Check if there is a default for this view for this specific user
|
|
220
228
|
if not isinstance(user, AnonymousUser):
|
|
221
229
|
try:
|
|
@@ -1051,7 +1059,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAnd
|
|
|
1051
1059
|
|
|
1052
1060
|
if form.is_valid():
|
|
1053
1061
|
logger.debug("Form validation was successful")
|
|
1054
|
-
return self.send_bulk_edit_objects_to_job(request, form, model)
|
|
1062
|
+
return self.send_bulk_edit_objects_to_job(request, form.cleaned_data, model)
|
|
1055
1063
|
else:
|
|
1056
1064
|
logger.debug("Form validation failed")
|
|
1057
1065
|
|
nautobot/core/views/mixins.py
CHANGED
|
@@ -723,8 +723,16 @@ class ObjectListViewMixin(NautobotViewSetMixin, mixins.ListModelMixin):
|
|
|
723
723
|
if response is not None:
|
|
724
724
|
return response
|
|
725
725
|
|
|
726
|
+
skip_user_and_global_default_saved_view = False
|
|
727
|
+
if self.filterset_class is not None:
|
|
728
|
+
skip_user_and_global_default_saved_view = get_filterable_params_from_filter_params(
|
|
729
|
+
request.GET.copy(),
|
|
730
|
+
self.non_filter_params,
|
|
731
|
+
self.filterset_class(),
|
|
732
|
+
)
|
|
733
|
+
|
|
726
734
|
# If the user clicks on the clear view button, we do not check for global or user defaults
|
|
727
|
-
if not clear_view and not request.GET.get("saved_view"):
|
|
735
|
+
if not skip_user_and_global_default_saved_view and not clear_view and not request.GET.get("saved_view"):
|
|
728
736
|
# Check if there is a default for this view for this specific user
|
|
729
737
|
app_label, model_name = queryset.model._meta.label.split(".")
|
|
730
738
|
view_name = f"{app_label}:{model_name.lower()}_list"
|
|
@@ -992,10 +1000,9 @@ class BulkEditAndBulkDeleteModelMixin:
|
|
|
992
1000
|
)
|
|
993
1001
|
return redirect("extras:jobresult", pk=job_result.pk)
|
|
994
1002
|
|
|
995
|
-
def send_bulk_edit_objects_to_job(self, request,
|
|
1003
|
+
def send_bulk_edit_objects_to_job(self, request, form_data, model):
|
|
996
1004
|
"""Prepare and enqueue a bulk edit job."""
|
|
997
1005
|
job_model = Job.objects.get_for_class_path(BulkEditObjects.class_path)
|
|
998
|
-
form_data = normalize_querydict(request.POST, form)
|
|
999
1006
|
if filterset_class := lookup.get_filterset_for_model(model):
|
|
1000
1007
|
filter_query_params = normalize_querydict(request.GET, filterset=filterset_class())
|
|
1001
1008
|
else:
|
|
@@ -1288,7 +1295,7 @@ class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin, Bulk
|
|
|
1288
1295
|
form = form_class(queryset.model, request.POST, edit_all=edit_all)
|
|
1289
1296
|
restrict_form_fields(form, request.user)
|
|
1290
1297
|
if form.is_valid():
|
|
1291
|
-
return self.send_bulk_edit_objects_to_job(self.request, form, queryset.model)
|
|
1298
|
+
return self.send_bulk_edit_objects_to_job(self.request, form.cleaned_data, queryset.model)
|
|
1292
1299
|
else:
|
|
1293
1300
|
return self.form_invalid(form)
|
|
1294
1301
|
table = None
|
|
@@ -1312,10 +1319,14 @@ class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin, Bulk
|
|
|
1312
1319
|
|
|
1313
1320
|
class ObjectChangeLogViewMixin(NautobotViewSetMixin):
|
|
1314
1321
|
"""
|
|
1315
|
-
UI mixin to list a model's changelog queryset
|
|
1322
|
+
UI mixin to list a model's changelog queryset.
|
|
1323
|
+
|
|
1324
|
+
base_template: Specify to explicitly identify the base object detail template to render.
|
|
1325
|
+
If not provided, "<app>/<model>.html", "<app>/<model>_retrieve.html", or "generic/object_retrieve.html"
|
|
1326
|
+
will be used, as per `get_base_template()`.
|
|
1316
1327
|
"""
|
|
1317
1328
|
|
|
1318
|
-
base_template = None
|
|
1329
|
+
base_template: Optional[str] = None
|
|
1319
1330
|
|
|
1320
1331
|
@drf_action(detail=True)
|
|
1321
1332
|
def changelog(self, request, *args, **kwargs):
|
|
@@ -1330,9 +1341,13 @@ class ObjectChangeLogViewMixin(NautobotViewSetMixin):
|
|
|
1330
1341
|
class ObjectNotesViewMixin(NautobotViewSetMixin):
|
|
1331
1342
|
"""
|
|
1332
1343
|
UI Mixin for an Object's Notes.
|
|
1344
|
+
|
|
1345
|
+
base_template: Specify to explicitly identify the base object detail template to render.
|
|
1346
|
+
If not provided, "<app>/<model>.html", "<app>/<model>_retrieve.html", or "generic/object_retrieve.html"
|
|
1347
|
+
will be used, as per `get_base_template()`.
|
|
1333
1348
|
"""
|
|
1334
1349
|
|
|
1335
|
-
base_template = None
|
|
1350
|
+
base_template: Optional[str] = None
|
|
1336
1351
|
|
|
1337
1352
|
@drf_action(detail=True)
|
|
1338
1353
|
def notes(self, request, *args, **kwargs):
|
nautobot/core/views/utils.py
CHANGED
|
@@ -137,10 +137,10 @@ def get_csv_form_fields_from_serializer_class(serializer_class):
|
|
|
137
137
|
elif cf.type == CustomFieldTypeChoices.TYPE_DATE:
|
|
138
138
|
field_info["format"] = mark_safe("<code>YYYY-MM-DD</code>") # noqa: S308
|
|
139
139
|
elif cf.type == CustomFieldTypeChoices.TYPE_SELECT:
|
|
140
|
-
field_info["choices"] = {
|
|
140
|
+
field_info["choices"] = {value: value for value in cf.choices}
|
|
141
141
|
elif cf.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
|
|
142
142
|
field_info["format"] = mark_safe('<code>"value,value"</code>') # noqa: S308
|
|
143
|
-
field_info["choices"] = {
|
|
143
|
+
field_info["choices"] = {value: value for value in cf.choices}
|
|
144
144
|
fields.append(field_info)
|
|
145
145
|
continue
|
|
146
146
|
|
nautobot/dcim/api/views.py
CHANGED
|
@@ -74,6 +74,7 @@ from nautobot.dcim.models import (
|
|
|
74
74
|
)
|
|
75
75
|
from nautobot.extras.api.views import (
|
|
76
76
|
ConfigContextQuerySetMixin,
|
|
77
|
+
CustomFieldModelViewSet,
|
|
77
78
|
NautobotModelViewSet,
|
|
78
79
|
)
|
|
79
80
|
from nautobot.extras.choices import SecretsGroupAccessTypeChoices, SecretsGroupSecretTypeChoices
|
|
@@ -300,13 +301,13 @@ class DeviceTypeViewSet(NautobotModelViewSet):
|
|
|
300
301
|
#
|
|
301
302
|
|
|
302
303
|
|
|
303
|
-
class ConsolePortTemplateViewSet(
|
|
304
|
+
class ConsolePortTemplateViewSet(CustomFieldModelViewSet):
|
|
304
305
|
queryset = ConsolePortTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
305
306
|
serializer_class = serializers.ConsolePortTemplateSerializer
|
|
306
307
|
filterset_class = filters.ConsolePortTemplateFilterSet
|
|
307
308
|
|
|
308
309
|
|
|
309
|
-
class ConsoleServerPortTemplateViewSet(
|
|
310
|
+
class ConsoleServerPortTemplateViewSet(CustomFieldModelViewSet):
|
|
310
311
|
queryset = ConsoleServerPortTemplate.objects.select_related(
|
|
311
312
|
"device_type__manufacturer", "module_type__manufacturer"
|
|
312
313
|
)
|
|
@@ -314,43 +315,43 @@ class ConsoleServerPortTemplateViewSet(NautobotModelViewSet):
|
|
|
314
315
|
filterset_class = filters.ConsoleServerPortTemplateFilterSet
|
|
315
316
|
|
|
316
317
|
|
|
317
|
-
class PowerPortTemplateViewSet(
|
|
318
|
+
class PowerPortTemplateViewSet(CustomFieldModelViewSet):
|
|
318
319
|
queryset = PowerPortTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
319
320
|
serializer_class = serializers.PowerPortTemplateSerializer
|
|
320
321
|
filterset_class = filters.PowerPortTemplateFilterSet
|
|
321
322
|
|
|
322
323
|
|
|
323
|
-
class PowerOutletTemplateViewSet(
|
|
324
|
+
class PowerOutletTemplateViewSet(CustomFieldModelViewSet):
|
|
324
325
|
queryset = PowerOutletTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
325
326
|
serializer_class = serializers.PowerOutletTemplateSerializer
|
|
326
327
|
filterset_class = filters.PowerOutletTemplateFilterSet
|
|
327
328
|
|
|
328
329
|
|
|
329
|
-
class InterfaceTemplateViewSet(
|
|
330
|
+
class InterfaceTemplateViewSet(CustomFieldModelViewSet):
|
|
330
331
|
queryset = InterfaceTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
331
332
|
serializer_class = serializers.InterfaceTemplateSerializer
|
|
332
333
|
filterset_class = filters.InterfaceTemplateFilterSet
|
|
333
334
|
|
|
334
335
|
|
|
335
|
-
class FrontPortTemplateViewSet(
|
|
336
|
+
class FrontPortTemplateViewSet(CustomFieldModelViewSet):
|
|
336
337
|
queryset = FrontPortTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
337
338
|
serializer_class = serializers.FrontPortTemplateSerializer
|
|
338
339
|
filterset_class = filters.FrontPortTemplateFilterSet
|
|
339
340
|
|
|
340
341
|
|
|
341
|
-
class RearPortTemplateViewSet(
|
|
342
|
+
class RearPortTemplateViewSet(CustomFieldModelViewSet):
|
|
342
343
|
queryset = RearPortTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
343
344
|
serializer_class = serializers.RearPortTemplateSerializer
|
|
344
345
|
filterset_class = filters.RearPortTemplateFilterSet
|
|
345
346
|
|
|
346
347
|
|
|
347
|
-
class DeviceBayTemplateViewSet(
|
|
348
|
+
class DeviceBayTemplateViewSet(CustomFieldModelViewSet):
|
|
348
349
|
queryset = DeviceBayTemplate.objects.select_related("device_type__manufacturer")
|
|
349
350
|
serializer_class = serializers.DeviceBayTemplateSerializer
|
|
350
351
|
filterset_class = filters.DeviceBayTemplateFilterSet
|
|
351
352
|
|
|
352
353
|
|
|
353
|
-
class ModuleBayTemplateViewSet(
|
|
354
|
+
class ModuleBayTemplateViewSet(CustomFieldModelViewSet):
|
|
354
355
|
queryset = ModuleBayTemplate.objects.select_related("device_type__manufacturer", "module_type__manufacturer")
|
|
355
356
|
serializer_class = serializers.ModuleBayTemplateSerializer
|
|
356
357
|
filterset_class = filters.ModuleBayTemplateFilterSet
|
|
@@ -831,7 +832,7 @@ class VirtualDeviceContextViewSet(NautobotModelViewSet):
|
|
|
831
832
|
filterset_class = filters.VirtualDeviceContextFilterSet
|
|
832
833
|
|
|
833
834
|
|
|
834
|
-
class InterfaceVDCAssignmentViewSet(
|
|
835
|
+
class InterfaceVDCAssignmentViewSet(ModelViewSet):
|
|
835
836
|
queryset = InterfaceVDCAssignment.objects.all()
|
|
836
837
|
serializer_class = serializers.InterfaceVDCAssignmentSerializer
|
|
837
838
|
filterset_class = filters.InterfaceVDCAssignmentFilterSet
|
nautobot/dcim/forms.py
CHANGED
|
@@ -17,6 +17,7 @@ from nautobot.core.forms import (
|
|
|
17
17
|
AutoPositionPatternField,
|
|
18
18
|
BootstrapMixin,
|
|
19
19
|
BulkEditNullBooleanSelect,
|
|
20
|
+
ClearableFileInput,
|
|
20
21
|
ColorSelect,
|
|
21
22
|
CommentField,
|
|
22
23
|
DatePicker,
|
|
@@ -307,6 +308,17 @@ class LocationTypeFilterForm(NautobotFilterForm):
|
|
|
307
308
|
content_types = MultipleContentTypeField(feature="locations", choices_as_strings=True, required=False)
|
|
308
309
|
|
|
309
310
|
|
|
311
|
+
class LocationTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
312
|
+
pk = forms.ModelMultipleChoiceField(queryset=LocationType.objects.all(), widget=forms.MultipleHiddenInput())
|
|
313
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
314
|
+
nestable = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect)
|
|
315
|
+
add_content_types = MultipleContentTypeField(feature="locations", required=False)
|
|
316
|
+
remove_content_types = MultipleContentTypeField(feature="locations", required=False)
|
|
317
|
+
|
|
318
|
+
class Meta:
|
|
319
|
+
nullable_fields = []
|
|
320
|
+
|
|
321
|
+
|
|
310
322
|
#
|
|
311
323
|
# Locations
|
|
312
324
|
#
|
|
@@ -784,6 +796,7 @@ class DeviceFamilyForm(NautobotModelForm):
|
|
|
784
796
|
fields = [
|
|
785
797
|
"name",
|
|
786
798
|
"description",
|
|
799
|
+
"tags",
|
|
787
800
|
]
|
|
788
801
|
|
|
789
802
|
|
|
@@ -838,12 +851,8 @@ class DeviceTypeForm(NautobotModelForm):
|
|
|
838
851
|
widgets = {
|
|
839
852
|
"subdevice_role": StaticSelect2(),
|
|
840
853
|
# Exclude SVG images (unsupported by PIL)
|
|
841
|
-
"front_image":
|
|
842
|
-
|
|
843
|
-
),
|
|
844
|
-
"rear_image": forms.ClearableFileInput(
|
|
845
|
-
attrs={"accept": "image/bmp,image/gif,image/jpeg,image/png,image/tiff"}
|
|
846
|
-
),
|
|
854
|
+
"front_image": ClearableFileInput(attrs={"accept": "image/bmp,image/gif,image/jpeg,image/png,image/tiff"}),
|
|
855
|
+
"rear_image": ClearableFileInput(attrs={"accept": "image/bmp,image/gif,image/jpeg,image/png,image/tiff"}),
|
|
847
856
|
}
|
|
848
857
|
|
|
849
858
|
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -1419,11 +1419,10 @@ class Controller(PrimaryModel):
|
|
|
1419
1419
|
"controller_device": ("Cannot assign both a device and a device redundancy group to a controller."),
|
|
1420
1420
|
},
|
|
1421
1421
|
)
|
|
1422
|
-
|
|
1423
1422
|
if self.location:
|
|
1424
1423
|
if ContentType.objects.get_for_model(self) not in self.location.location_type.content_types.all():
|
|
1425
1424
|
raise ValidationError(
|
|
1426
|
-
{"location": f'
|
|
1425
|
+
{"location": f'Controllers may not associate to locations of type "{self.location.location_type}".'}
|
|
1427
1426
|
)
|
|
1428
1427
|
|
|
1429
1428
|
def get_capabilities_display(self):
|
nautobot/dcim/tables/devices.py
CHANGED
|
@@ -106,7 +106,8 @@ __all__ = (
|
|
|
106
106
|
|
|
107
107
|
class PlatformTable(BaseTable):
|
|
108
108
|
pk = ToggleColumn()
|
|
109
|
-
name = tables.
|
|
109
|
+
name = tables.Column(linkify=True)
|
|
110
|
+
manufacturer = tables.Column(linkify=True)
|
|
110
111
|
device_count = LinkedCountColumn(
|
|
111
112
|
viewname="dcim:device_list",
|
|
112
113
|
url_params={"platform": "pk"},
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
{% for near_end, cable, far_end in traced_path %}
|
|
14
14
|
|
|
15
15
|
{# Near end #}
|
|
16
|
-
{% if near_end.device %}
|
|
17
|
-
{% include 'dcim/trace/device.html' with device=near_end.
|
|
16
|
+
{% if near_end.device or near_end.module %}
|
|
17
|
+
{% include 'dcim/trace/device.html' with device=near_end.parent %}
|
|
18
18
|
{% include 'dcim/trace/termination.html' with termination=near_end %}
|
|
19
19
|
{% elif near_end.power_panel %}
|
|
20
20
|
{% include 'dcim/trace/powerpanel.html' with powerpanel=near_end.power_panel %}
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
{% endif %}
|
|
31
31
|
|
|
32
32
|
{# Far end #}
|
|
33
|
-
{% if far_end.device %}
|
|
33
|
+
{% if far_end.device or far_end.module %}
|
|
34
34
|
{% include 'dcim/trace/termination.html' with termination=far_end %}
|
|
35
35
|
{% if forloop.last %}
|
|
36
|
-
{% include 'dcim/trace/device.html' with device=far_end.
|
|
36
|
+
{% include 'dcim/trace/device.html' with device=far_end.parent %}
|
|
37
37
|
{% endif %}
|
|
38
38
|
{% elif far_end.power_panel %}
|
|
39
39
|
{% include 'dcim/trace/termination.html' with termination=far_end %}
|
|
@@ -8,8 +8,13 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
<table class="table table-hover panel-body attr-table">
|
|
10
10
|
<tr>
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
{% if object.device %}
|
|
12
|
+
<td>Device</td>
|
|
13
|
+
<td>{{ object.device|hyperlinked_object }}</td>
|
|
14
|
+
{% else %}
|
|
15
|
+
<td>Module</td>
|
|
16
|
+
<td>{{ object.module|hyperlinked_object }}</td>
|
|
17
|
+
{% endif %}
|
|
13
18
|
</tr>
|
|
14
19
|
<tr>
|
|
15
20
|
<td>Name</td>
|
|
@@ -49,8 +54,13 @@
|
|
|
49
54
|
</tr>
|
|
50
55
|
{% if object.connected_endpoint %}
|
|
51
56
|
<tr>
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
{% if object.connected_endpoint.device %}
|
|
58
|
+
<td>Device</td>
|
|
59
|
+
<td>{{ object.connected_endpoint.device|hyperlinked_object }}</td>
|
|
60
|
+
{% else %}
|
|
61
|
+
<td>Module</td>
|
|
62
|
+
<td>{{ object.connected_endpoint.module|hyperlinked_object }}</td>
|
|
63
|
+
{% endif %}
|
|
54
64
|
</tr>
|
|
55
65
|
<tr>
|
|
56
66
|
<td>Console Server Port</td>
|
|
@@ -8,8 +8,13 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
<table class="table table-hover panel-body attr-table">
|
|
10
10
|
<tr>
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
{% if object.device %}
|
|
12
|
+
<td>Device</td>
|
|
13
|
+
<td>{{ object.device|hyperlinked_object }}</td>
|
|
14
|
+
{% else %}
|
|
15
|
+
<td>Module</td>
|
|
16
|
+
<td>{{ object.module|hyperlinked_object }}</td>
|
|
17
|
+
{% endif %}
|
|
13
18
|
</tr>
|
|
14
19
|
<tr>
|
|
15
20
|
<td>Name</td>
|
|
@@ -49,8 +54,13 @@
|
|
|
49
54
|
</tr>
|
|
50
55
|
{% if object.connected_endpoint %}
|
|
51
56
|
<tr>
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
{% if object.connected_endpoint.device %}
|
|
58
|
+
<td>Device</td>
|
|
59
|
+
<td>{{ object.connected_endpoint.device|hyperlinked_object }}</td>
|
|
60
|
+
{% else %}
|
|
61
|
+
<td>Module</td>
|
|
62
|
+
<td>{{ object.connected_endpoint.module|hyperlinked_object }}</td>
|
|
63
|
+
{% endif %}
|
|
54
64
|
</tr>
|
|
55
65
|
<tr>
|
|
56
66
|
<td>Console Port</td>
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
{% for iface in interfaces %}
|
|
25
25
|
<tr data-interface-name="{{ iface.name }}">
|
|
26
26
|
<td>{{ iface }}</td>
|
|
27
|
-
{% if iface.connected_endpoint.device %}
|
|
28
|
-
<td class="configured_device" data="{{ iface.connected_endpoint.
|
|
29
|
-
{{ iface.connected_endpoint.
|
|
27
|
+
{% if iface.connected_endpoint.device or iface.connected_endpoint.module %}
|
|
28
|
+
<td class="configured_device" data="{{ iface.connected_endpoint.parent }}" data-chassis="{{ iface.connected_endpoint.parent.virtual_chassis.name }}">
|
|
29
|
+
{{ iface.connected_endpoint.parent|hyperlinked_object }}
|
|
30
30
|
</td>
|
|
31
31
|
<td class="configured_interface" data-interface-name="{{ iface.connected_endpoint }}">
|
|
32
32
|
<span title="{{ iface.connected_endpoint.get_type_display }}">{{ iface.connected_endpoint }}</span>
|
|
@@ -214,8 +214,8 @@
|
|
|
214
214
|
<tr>
|
|
215
215
|
<td>Cluster</td>
|
|
216
216
|
<td>
|
|
217
|
-
{% if object.cluster.
|
|
218
|
-
{{ object.cluster.
|
|
217
|
+
{% if object.cluster.cluster_group %}
|
|
218
|
+
{{ object.cluster.cluster_group|hyperlinked_object }} /
|
|
219
219
|
{% endif %}
|
|
220
220
|
{{ object.cluster|hyperlinked_object }}
|
|
221
221
|
</td>
|
|
@@ -8,8 +8,13 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
<table class="table table-hover panel-body attr-table">
|
|
10
10
|
<tr>
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
{% if object.device %}
|
|
12
|
+
<td>Device</td>
|
|
13
|
+
<td>{{ object.device|hyperlinked_object }}</td>
|
|
14
|
+
{% else %}
|
|
15
|
+
<td>Module</td>
|
|
16
|
+
<td>{{ object.module|hyperlinked_object }}</td>
|
|
17
|
+
{% endif %}
|
|
13
18
|
</tr>
|
|
14
19
|
<tr>
|
|
15
20
|
<td>Name</td>
|
|
@@ -101,11 +101,16 @@
|
|
|
101
101
|
</a>
|
|
102
102
|
</td>
|
|
103
103
|
</tr>
|
|
104
|
-
{% if object.connected_endpoint.device %}
|
|
104
|
+
{% if object.connected_endpoint.device or object.connected_endpoint.module %}
|
|
105
105
|
{% with iface=object.connected_endpoint %}
|
|
106
106
|
<tr>
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
{% if iface.device %}
|
|
108
|
+
<td>Device</td>
|
|
109
|
+
<td>{{ iface.device|hyperlinked_object }}</td>
|
|
110
|
+
{% else %}
|
|
111
|
+
<td>Module</td>
|
|
112
|
+
<td>{{ iface.module|hyperlinked_object }}</td>
|
|
113
|
+
{% endif %}
|
|
109
114
|
</tr>
|
|
110
115
|
<tr>
|
|
111
116
|
<td>Interface</td>
|
|
@@ -201,7 +206,7 @@
|
|
|
201
206
|
<tbody>
|
|
202
207
|
{% for member in object.member_interfaces.all %}
|
|
203
208
|
<tr>
|
|
204
|
-
<td>{{ member.
|
|
209
|
+
<td>{{ member.parent|hyperlinked_object }}</td>
|
|
205
210
|
<td>{{ member|hyperlinked_object }}</td>
|
|
206
211
|
<td>
|
|
207
212
|
{{ member.get_type_display }}
|