nautobot 2.4.13__py3-none-any.whl → 2.4.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nautobot/core/graphql/generators.py +8 -0
- nautobot/core/graphql/schema.py +30 -30
- nautobot/core/management/commands/migrate.py +90 -1
- nautobot/core/settings.yaml +3 -3
- nautobot/core/tables.py +4 -4
- nautobot/core/testing/api.py +7 -0
- nautobot/core/views/utils.py +1 -1
- nautobot/dcim/choices.py +2 -0
- nautobot/dcim/constants.py +0 -16
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/templates/dcim/rack.html +2 -318
- nautobot/dcim/templates/dcim/rack_edit.html +2 -47
- nautobot/dcim/templates/dcim/rack_retrieve.html +318 -0
- nautobot/dcim/templates/dcim/rack_update.html +47 -0
- nautobot/dcim/urls.py +2 -27
- nautobot/dcim/utils.py +4 -30
- nautobot/dcim/views.py +38 -69
- nautobot/extras/choices.py +12 -4
- nautobot/extras/filters/mixins.py +8 -6
- nautobot/extras/forms/forms.py +9 -0
- nautobot/extras/forms/mixins.py +4 -2
- nautobot/extras/migrations/0062_collect_roles_from_related_apps_roles.py +30 -7
- nautobot/extras/migrations/0124_add_joblogentry_index.py +16 -0
- nautobot/extras/models/customfields.py +52 -3
- nautobot/extras/models/jobs.py +6 -0
- nautobot/extras/models/relationships.py +55 -6
- nautobot/extras/templates/extras/graphqlquery.html +2 -97
- nautobot/extras/templates/extras/graphqlquery_list.html +1 -0
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +97 -0
- nautobot/extras/templates/extras/secretsgroup.html +2 -29
- nautobot/extras/templates/extras/secretsgroup_edit.html +2 -82
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +29 -0
- nautobot/extras/templates/extras/secretsgroup_update.html +82 -0
- nautobot/extras/tests/test_customfields.py +115 -7
- nautobot/extras/tests/test_relationships.py +7 -1
- nautobot/extras/tests/test_views.py +113 -1
- nautobot/extras/urls.py +2 -51
- nautobot/extras/utils.py +4 -1
- nautobot/extras/views.py +39 -133
- nautobot/ipam/api/views.py +69 -6
- nautobot/ipam/tests/test_api.py +350 -0
- nautobot/project-static/docs/404.html +11 -34
- nautobot/project-static/docs/apps/index.html +11 -34
- nautobot/project-static/docs/apps/nautobot-apps.html +11 -34
- nautobot/project-static/docs/assets/javascripts/{bundle.56ea9cef.min.js → bundle.50899def.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.56ea9cef.min.js.map → bundle.50899def.min.js.map} +2 -2
- nautobot/project-static/docs/assets/stylesheets/{main.342714a4.min.css → main.7e37652d.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.342714a4.min.css.map → main.7e37652d.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +11 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +11 -34
- nautobot/project-static/docs/development/apps/api/configuration-view.html +11 -34
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -34
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +11 -34
- nautobot/project-static/docs/development/apps/api/models/global-search.html +11 -34
- nautobot/project-static/docs/development/apps/api/models/graphql.html +11 -34
- nautobot/project-static/docs/development/apps/api/models/index.html +11 -34
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +11 -34
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +11 -34
- nautobot/project-static/docs/development/apps/api/prometheus.html +11 -34
- nautobot/project-static/docs/development/apps/api/setup.html +11 -34
- nautobot/project-static/docs/development/apps/api/testing.html +11 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +11 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +11 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +11 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +11 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/base-template.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/index.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/notes.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +11 -34
- nautobot/project-static/docs/development/apps/api/views/urls.html +11 -34
- nautobot/project-static/docs/development/apps/index.html +11 -34
- nautobot/project-static/docs/development/apps/migration/code-updates.html +11 -34
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +11 -34
- nautobot/project-static/docs/development/apps/migration/from-v1.html +11 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +11 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +11 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +11 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +11 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +11 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +11 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +11 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +11 -34
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +11 -34
- nautobot/project-static/docs/development/core/application-registry.html +139 -133
- nautobot/project-static/docs/development/core/best-practices.html +11 -34
- nautobot/project-static/docs/development/core/bootstrap-ui.html +11 -34
- nautobot/project-static/docs/development/core/caching.html +11 -34
- nautobot/project-static/docs/development/core/controllers.html +11 -34
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +11 -34
- nautobot/project-static/docs/development/core/generic-views.html +11 -34
- nautobot/project-static/docs/development/core/getting-started.html +11 -34
- nautobot/project-static/docs/development/core/homepage.html +11 -34
- nautobot/project-static/docs/development/core/index.html +11 -34
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +11 -34
- nautobot/project-static/docs/development/core/model-checklist.html +11 -34
- nautobot/project-static/docs/development/core/model-features.html +11 -34
- nautobot/project-static/docs/development/core/natural-keys.html +11 -34
- nautobot/project-static/docs/development/core/navigation-menu.html +11 -34
- nautobot/project-static/docs/development/core/release-checklist.html +11 -34
- nautobot/project-static/docs/development/core/role-internals.html +11 -34
- nautobot/project-static/docs/development/core/settings.html +11 -34
- nautobot/project-static/docs/development/core/style-guide.html +11 -34
- nautobot/project-static/docs/development/core/templates.html +11 -34
- nautobot/project-static/docs/development/core/testing.html +11 -34
- nautobot/project-static/docs/development/core/ui-component-framework.html +11 -34
- nautobot/project-static/docs/development/core/user-preferences.html +11 -34
- nautobot/project-static/docs/development/index.html +11 -34
- nautobot/project-static/docs/development/jobs/getting-started.html +11 -34
- nautobot/project-static/docs/development/jobs/index.html +11 -34
- nautobot/project-static/docs/development/jobs/installation.html +11 -34
- nautobot/project-static/docs/development/jobs/job-extensions.html +11 -34
- nautobot/project-static/docs/development/jobs/job-logging.html +11 -34
- nautobot/project-static/docs/development/jobs/job-patterns.html +11 -34
- nautobot/project-static/docs/development/jobs/job-structure.html +11 -34
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +11 -34
- nautobot/project-static/docs/development/jobs/testing.html +11 -34
- nautobot/project-static/docs/index.html +11 -34
- nautobot/project-static/docs/overview/application_stack.html +11 -34
- nautobot/project-static/docs/overview/design_philosophy.html +11 -34
- nautobot/project-static/docs/release-notes/index.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.0.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.1.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.2.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.3.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.4.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.5.html +11 -34
- nautobot/project-static/docs/release-notes/version-1.6.html +11 -34
- nautobot/project-static/docs/release-notes/version-2.0.html +11 -34
- nautobot/project-static/docs/release-notes/version-2.1.html +11 -34
- nautobot/project-static/docs/release-notes/version-2.2.html +11 -34
- nautobot/project-static/docs/release-notes/version-2.3.html +11 -34
- nautobot/project-static/docs/release-notes/version-2.4.html +171 -34
- nautobot/project-static/docs/requirements.txt +1 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +299 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +11 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +11 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +11 -34
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +11 -34
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +11 -34
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +14 -37
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +11 -34
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/index.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +11 -34
- nautobot/project-static/docs/user-guide/administration/installation/services.html +11 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +11 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +11 -34
- nautobot/project-static/docs/user-guide/administration/security/index.html +11 -34
- nautobot/project-static/docs/user-guide/administration/security/notices.html +11 -34
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +19 -39
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +11 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +14 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +19 -52
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +14 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +11 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +11 -34
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +11 -34
- nautobot/project-static/docs/user-guide/index.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +11 -34
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +11 -34
- nautobot/tenancy/api/views.py +2 -1
- {nautobot-2.4.13.dist-info → nautobot-2.4.14.dist-info}/METADATA +5 -5
- {nautobot-2.4.13.dist-info → nautobot-2.4.14.dist-info}/RECORD +356 -349
- {nautobot-2.4.13.dist-info → nautobot-2.4.14.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.14.dist-info}/NOTICE +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.14.dist-info}/WHEEL +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.14.dist-info}/entry_points.txt +0 -0
|
@@ -74,7 +74,9 @@ class CustomFieldModelFilterSetMixin(django_filters.FilterSet):
|
|
|
74
74
|
CustomFieldTypeChoices.TYPE_SELECT: CustomFieldSelectFilter,
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
custom_fields = CustomField.objects.get_for_model(
|
|
77
|
+
custom_fields = CustomField.objects.get_for_model(
|
|
78
|
+
self._meta.model, exclude_filter_disabled=True, get_queryset=False
|
|
79
|
+
)
|
|
78
80
|
for cf in custom_fields:
|
|
79
81
|
# Determine filter class for this CustomField type, default to CustomFieldCharFilter
|
|
80
82
|
new_filter_name = cf.add_prefix_to_cf_key()
|
|
@@ -220,13 +222,13 @@ class RelationshipModelFilterSetMixin(django_filters.FilterSet):
|
|
|
220
222
|
"""
|
|
221
223
|
Append form fields for all Relationships assigned to this model.
|
|
222
224
|
"""
|
|
223
|
-
src_relationships, dst_relationships = Relationship.objects.get_for_model(
|
|
225
|
+
src_relationships, dst_relationships = Relationship.objects.get_for_model(
|
|
226
|
+
model=model, hidden=False, get_queryset=False
|
|
227
|
+
)
|
|
224
228
|
|
|
225
|
-
|
|
226
|
-
self._append_relationships_side([rel], RelationshipSideChoices.SIDE_SOURCE, model)
|
|
229
|
+
self._append_relationships_side(src_relationships, RelationshipSideChoices.SIDE_SOURCE, model)
|
|
227
230
|
|
|
228
|
-
|
|
229
|
-
self._append_relationships_side([rel], RelationshipSideChoices.SIDE_DESTINATION, model)
|
|
231
|
+
self._append_relationships_side(dst_relationships, RelationshipSideChoices.SIDE_DESTINATION, model)
|
|
230
232
|
|
|
231
233
|
def _append_relationships_side(self, relationships, initial_side, model):
|
|
232
234
|
"""
|
nautobot/extras/forms/forms.py
CHANGED
|
@@ -197,6 +197,7 @@ __all__ = (
|
|
|
197
197
|
"SecretFilterForm",
|
|
198
198
|
"SecretForm",
|
|
199
199
|
"SecretsGroupAssociationFormSet",
|
|
200
|
+
"SecretsGroupBulkEditForm",
|
|
200
201
|
"SecretsGroupFilterForm",
|
|
201
202
|
"SecretsGroupForm",
|
|
202
203
|
"StaticGroupAssociationFilterForm",
|
|
@@ -2082,6 +2083,14 @@ class RoleFilterForm(NautobotFilterForm):
|
|
|
2082
2083
|
#
|
|
2083
2084
|
|
|
2084
2085
|
|
|
2086
|
+
class SecretsGroupBulkEditForm(NautobotBulkEditForm):
|
|
2087
|
+
pk = forms.ModelMultipleChoiceField(queryset=SecretsGroup.objects.all(), widget=forms.MultipleHiddenInput())
|
|
2088
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
2089
|
+
|
|
2090
|
+
class Meta:
|
|
2091
|
+
model = SecretsGroup
|
|
2092
|
+
|
|
2093
|
+
|
|
2085
2094
|
def provider_choices():
|
|
2086
2095
|
return sorted([(slug, provider.name) for slug, provider in registry["secrets_providers"].items()])
|
|
2087
2096
|
|
nautobot/extras/forms/mixins.py
CHANGED
|
@@ -95,7 +95,7 @@ class CustomFieldModelFilterFormMixin(forms.Form):
|
|
|
95
95
|
def __init__(self, *args, **kwargs):
|
|
96
96
|
super().__init__(*args, **kwargs)
|
|
97
97
|
|
|
98
|
-
custom_fields = CustomField.objects.get_for_model(self.model, exclude_filter_disabled=True)
|
|
98
|
+
custom_fields = CustomField.objects.get_for_model(self.model, exclude_filter_disabled=True, get_queryset=False)
|
|
99
99
|
self.custom_fields = []
|
|
100
100
|
for cf in custom_fields:
|
|
101
101
|
field_name = cf.add_prefix_to_cf_key()
|
|
@@ -714,7 +714,9 @@ class RelationshipModelFilterFormMixin(forms.Form):
|
|
|
714
714
|
"""
|
|
715
715
|
Append form fields for all Relationships assigned to this model.
|
|
716
716
|
"""
|
|
717
|
-
src_relationships, dst_relationships = Relationship.objects.get_for_model(
|
|
717
|
+
src_relationships, dst_relationships = Relationship.objects.get_for_model(
|
|
718
|
+
model=self.model, hidden=False, get_queryset=False
|
|
719
|
+
)
|
|
718
720
|
|
|
719
721
|
for rel in src_relationships:
|
|
720
722
|
self._append_relationships_side([rel], RelationshipSideChoices.SIDE_SOURCE)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Generated by Django 3.2.16 on 2022-11-19 23:15
|
|
2
2
|
|
|
3
3
|
from collections import namedtuple
|
|
4
|
-
import logging
|
|
5
4
|
|
|
6
5
|
from django.db import migrations, models
|
|
7
6
|
|
|
@@ -24,8 +23,6 @@ color_map = {
|
|
|
24
23
|
"success": ColorChoices.COLOR_GREEN,
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
logger = logging.getLogger(__name__)
|
|
28
|
-
|
|
29
26
|
|
|
30
27
|
def create_equivalent_roles_of_virtualmachine_device_role(apps):
|
|
31
28
|
"""Create equivalent roles for the VirtualMachine DeviceRole."""
|
|
@@ -82,17 +79,43 @@ def create_roles(apps, roles_to_create, content_types):
|
|
|
82
79
|
"description": old_role.description,
|
|
83
80
|
"color": getattr(old_role, "color", color_map["default"]),
|
|
84
81
|
"weight": getattr(old_role, "weight", None),
|
|
82
|
+
"_custom_field_data": getattr(old_role, "_custom_field_data", {}),
|
|
85
83
|
},
|
|
86
84
|
)
|
|
87
85
|
if created:
|
|
88
|
-
|
|
86
|
+
print(f" Created Role {new_role.name!r}")
|
|
87
|
+
else:
|
|
88
|
+
updated = False
|
|
89
|
+
# Fix up in the case of overlapping roles
|
|
90
|
+
if new_role.weight is None and hasattr(old_role, "weight"):
|
|
91
|
+
new_role.weight = old_role.weight
|
|
92
|
+
updated = True
|
|
93
|
+
if old_role.description and not new_role.description:
|
|
94
|
+
new_role.description = old_role.description
|
|
95
|
+
updated = True
|
|
96
|
+
if hasattr(old_role, "_custom_field_data"):
|
|
97
|
+
for field, value in old_role._custom_field_data.items():
|
|
98
|
+
if field in new_role._custom_field_data:
|
|
99
|
+
if new_role._custom_field_data[field] != value:
|
|
100
|
+
print(
|
|
101
|
+
f" Value conflict for custom field {field!r} for role {new_role.name!r} - DATA LOSS"
|
|
102
|
+
)
|
|
103
|
+
else:
|
|
104
|
+
new_role._custom_field_data[field] = value
|
|
105
|
+
updated = True
|
|
106
|
+
if updated:
|
|
107
|
+
print(f" Updated Role {new_role.name!r}")
|
|
108
|
+
new_role.save()
|
|
109
|
+
else:
|
|
110
|
+
print(f" No changes to already-created Role {new_role.name!r}")
|
|
111
|
+
|
|
89
112
|
if old_role_ct and hasattr(old_role, "pk"):
|
|
90
113
|
# Move over existing object change records to the new role we created
|
|
91
114
|
updated_count = ObjectChange.objects.filter(
|
|
92
115
|
changed_object_type=old_role_ct, changed_object_id=old_role.pk
|
|
93
116
|
).update(changed_object_type=new_role_ct, changed_object_id=new_role.pk)
|
|
94
|
-
|
|
95
|
-
f
|
|
117
|
+
print(
|
|
118
|
+
f" Updated {updated_count} ObjectChanges from the existing {old_role.name!r} {old_role._meta.label}"
|
|
96
119
|
)
|
|
97
120
|
|
|
98
121
|
# This is for all of the change records for roles which no longer exist
|
|
@@ -100,7 +123,7 @@ def create_roles(apps, roles_to_create, content_types):
|
|
|
100
123
|
updated_count = ObjectChange.objects.filter(changed_object_type=old_role_ct).update(
|
|
101
124
|
changed_object_type=new_role_ct
|
|
102
125
|
)
|
|
103
|
-
|
|
126
|
+
print(f" Updated {updated_count} leftover ObjectChanges from deleted {old_role_ct.model} records.")
|
|
104
127
|
|
|
105
128
|
roles = Role.objects.filter(name__in=[roles.name for roles in roles_to_create])
|
|
106
129
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Generated by Django 4.2.23 on 2025-07-31 23:49
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("extras", "0123_alter_joblogentry_created"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.AddIndex(
|
|
13
|
+
model_name="joblogentry",
|
|
14
|
+
index=models.Index(fields=["job_result", "created"], name="extras_joblog_jr_created_idx"),
|
|
15
|
+
),
|
|
16
|
+
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from collections import OrderedDict
|
|
1
|
+
from collections import defaultdict, OrderedDict
|
|
2
2
|
from datetime import date, datetime
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
@@ -48,21 +48,42 @@ logger = logging.getLogger(__name__)
|
|
|
48
48
|
class ComputedFieldManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
49
49
|
use_in_migrations = True
|
|
50
50
|
|
|
51
|
-
def get_for_model(self, model):
|
|
51
|
+
def get_for_model(self, model, get_queryset=True):
|
|
52
52
|
"""
|
|
53
53
|
Return all ComputedFields assigned to the given model.
|
|
54
|
+
|
|
55
|
+
Returns a queryset by default, or a list if `get_queryset` param is False.
|
|
54
56
|
"""
|
|
55
57
|
concrete_model = model._meta.concrete_model
|
|
56
58
|
cache_key = f"{self.get_for_model.cache_key_prefix}.{concrete_model._meta.label_lower}"
|
|
59
|
+
list_cache_key = f"{cache_key}.list"
|
|
60
|
+
if not get_queryset:
|
|
61
|
+
listing = cache.get(list_cache_key)
|
|
62
|
+
if listing is not None:
|
|
63
|
+
return listing
|
|
57
64
|
queryset = cache.get(cache_key)
|
|
58
65
|
if queryset is None:
|
|
59
66
|
content_type = ContentType.objects.get_for_model(concrete_model)
|
|
60
67
|
queryset = self.get_queryset().filter(content_type=content_type)
|
|
61
68
|
cache.set(cache_key, queryset)
|
|
69
|
+
if not get_queryset:
|
|
70
|
+
listing = list(queryset)
|
|
71
|
+
cache.set(list_cache_key, listing)
|
|
72
|
+
return listing
|
|
62
73
|
return queryset
|
|
63
74
|
|
|
64
75
|
get_for_model.cache_key_prefix = "nautobot.extras.computedfield.get_for_model"
|
|
65
76
|
|
|
77
|
+
def populate_list_caches(self):
|
|
78
|
+
"""Populate all caches for `get_for_model(..., get_queryset=False)` lookups."""
|
|
79
|
+
queryset = self.all().select_related("content_type")
|
|
80
|
+
listings = defaultdict(list)
|
|
81
|
+
for cf in queryset:
|
|
82
|
+
listings[f"{cf.content_type.app_label}.{cf.content_type.model}"].append(cf)
|
|
83
|
+
for ct in ContentType.objects.all():
|
|
84
|
+
label = f"{ct.app_label}.{ct.model}"
|
|
85
|
+
cache.set(f"{self.get_for_model.cache_key_prefix}.{label}.list", listings[label])
|
|
86
|
+
|
|
66
87
|
|
|
67
88
|
@extras_features("graphql")
|
|
68
89
|
class ComputedField(
|
|
@@ -370,18 +391,24 @@ class CustomFieldModel(models.Model):
|
|
|
370
391
|
class CustomFieldManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
371
392
|
use_in_migrations = True
|
|
372
393
|
|
|
373
|
-
def get_for_model(self, model, exclude_filter_disabled=False):
|
|
394
|
+
def get_for_model(self, model, exclude_filter_disabled=False, get_queryset=True):
|
|
374
395
|
"""
|
|
375
396
|
Return (and cache) all CustomFields assigned to the given model.
|
|
376
397
|
|
|
377
398
|
Args:
|
|
378
399
|
model (Model): The django model to which custom fields are registered
|
|
379
400
|
exclude_filter_disabled (bool): Exclude any custom fields which have filter logic disabled
|
|
401
|
+
get_queryset (bool): Whether to return a QuerySet or a list.
|
|
380
402
|
"""
|
|
381
403
|
concrete_model = model._meta.concrete_model
|
|
382
404
|
cache_key = (
|
|
383
405
|
f"{self.get_for_model.cache_key_prefix}.{concrete_model._meta.label_lower}.{exclude_filter_disabled}"
|
|
384
406
|
)
|
|
407
|
+
list_cache_key = f"{cache_key}.list"
|
|
408
|
+
if not get_queryset:
|
|
409
|
+
listing = cache.get(list_cache_key)
|
|
410
|
+
if listing is not None:
|
|
411
|
+
return listing
|
|
385
412
|
queryset = cache.get(cache_key)
|
|
386
413
|
if queryset is None:
|
|
387
414
|
content_type = ContentType.objects.get_for_model(concrete_model)
|
|
@@ -389,6 +416,10 @@ class CustomFieldManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
|
389
416
|
if exclude_filter_disabled:
|
|
390
417
|
queryset = queryset.exclude(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED)
|
|
391
418
|
cache.set(cache_key, queryset)
|
|
419
|
+
if not get_queryset:
|
|
420
|
+
listing = list(queryset)
|
|
421
|
+
cache.set(list_cache_key, listing)
|
|
422
|
+
return listing
|
|
392
423
|
return queryset
|
|
393
424
|
|
|
394
425
|
get_for_model.cache_key_prefix = "nautobot.extras.customfield.get_for_model"
|
|
@@ -405,6 +436,24 @@ class CustomFieldManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
|
405
436
|
|
|
406
437
|
keys_for_model.cache_key_prefix = "nautobot.extras.customfield.keys_for_model"
|
|
407
438
|
|
|
439
|
+
def populate_list_caches(self):
|
|
440
|
+
"""Populate all caches for `get_for_model(..., get_queryset=False)` and `keys_for_model` lookups."""
|
|
441
|
+
queryset = self.all().prefetch_related("content_types")
|
|
442
|
+
cf_listings = defaultdict(lambda: defaultdict(list))
|
|
443
|
+
key_listings = defaultdict(list)
|
|
444
|
+
for cf in queryset:
|
|
445
|
+
for ct in cf.content_types.all():
|
|
446
|
+
label = f"{ct.app_label}.{ct.model}"
|
|
447
|
+
cf_listings[label][False].append(cf)
|
|
448
|
+
if cf.filter_logic != CustomFieldFilterLogicChoices.FILTER_DISABLED:
|
|
449
|
+
cf_listings[label][True].append(cf)
|
|
450
|
+
key_listings[label].append(cf.key)
|
|
451
|
+
for ct in ContentType.objects.all():
|
|
452
|
+
label = f"{ct.app_label}.{ct.model}"
|
|
453
|
+
cache.set(f"{self.get_for_model.cache_key_prefix}.{label}.True.list", cf_listings[label][True])
|
|
454
|
+
cache.set(f"{self.get_for_model.cache_key_prefix}.{label}.False.list", cf_listings[label][False])
|
|
455
|
+
cache.set(f"{self.keys_for_model.cache_key_prefix}.{label}", key_listings[label])
|
|
456
|
+
|
|
408
457
|
|
|
409
458
|
@extras_features("webhooks")
|
|
410
459
|
class CustomField(
|
nautobot/extras/models/jobs.py
CHANGED
|
@@ -543,6 +543,12 @@ class JobLogEntry(BaseModel):
|
|
|
543
543
|
ordering = ["created"]
|
|
544
544
|
get_latest_by = "created"
|
|
545
545
|
verbose_name_plural = "job log entries"
|
|
546
|
+
indexes = [
|
|
547
|
+
models.Index(
|
|
548
|
+
name="extras_joblog_jr_created_idx",
|
|
549
|
+
fields=["job_result", "created"],
|
|
550
|
+
)
|
|
551
|
+
]
|
|
546
552
|
|
|
547
553
|
|
|
548
554
|
#
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
1
2
|
import logging
|
|
2
3
|
|
|
3
4
|
from django import forms
|
|
@@ -422,31 +423,38 @@ class RelationshipModel(models.Model):
|
|
|
422
423
|
class RelationshipManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
423
424
|
use_in_migrations = True
|
|
424
425
|
|
|
425
|
-
def get_for_model(self, model, hidden=None):
|
|
426
|
+
def get_for_model(self, model, hidden=None, get_queryset=True):
|
|
426
427
|
"""
|
|
427
428
|
Return all Relationships assigned to the given model.
|
|
428
429
|
|
|
429
430
|
Args:
|
|
430
431
|
model (Model): The django model to which relationships are registered
|
|
431
432
|
hidden (bool): Filter based on the value of the hidden flag, or None to not apply this filter
|
|
433
|
+
get_queryset (bool): Whether to return querysets or object lists.
|
|
432
434
|
|
|
433
|
-
Returns a tuple of source and destination scoped relationship querysets.
|
|
435
|
+
Returns a tuple of source and destination scoped relationship record querysets/lists.
|
|
434
436
|
"""
|
|
435
437
|
return (
|
|
436
|
-
self.get_for_model_source(model, hidden=hidden),
|
|
437
|
-
self.get_for_model_destination(model, hidden=hidden),
|
|
438
|
+
self.get_for_model_source(model, hidden=hidden, get_queryset=get_queryset),
|
|
439
|
+
self.get_for_model_destination(model, hidden=hidden, get_queryset=get_queryset),
|
|
438
440
|
)
|
|
439
441
|
|
|
440
|
-
def get_for_model_source(self, model, hidden=None):
|
|
442
|
+
def get_for_model_source(self, model, hidden=None, get_queryset=True):
|
|
441
443
|
"""
|
|
442
444
|
Return all Relationships assigned to the given model for the source side only.
|
|
443
445
|
|
|
444
446
|
Args:
|
|
445
447
|
model (Model): The django model to which relationships are registered
|
|
446
448
|
hidden (bool): Filter based on the value of the hidden flag, or None to not apply this filter
|
|
449
|
+
get_queryset (bool): Whether to return a queryset or an object list.
|
|
447
450
|
"""
|
|
448
451
|
concrete_model = model._meta.concrete_model
|
|
449
452
|
cache_key = f"{self.get_for_model_source.cache_key_prefix}.{concrete_model._meta.label_lower}.{hidden}"
|
|
453
|
+
list_cache_key = f"{cache_key}.list"
|
|
454
|
+
if not get_queryset:
|
|
455
|
+
listing = cache.get(list_cache_key)
|
|
456
|
+
if listing is not None:
|
|
457
|
+
return listing
|
|
450
458
|
queryset = cache.get(cache_key)
|
|
451
459
|
if queryset is None:
|
|
452
460
|
content_type = ContentType.objects.get_for_model(concrete_model)
|
|
@@ -456,20 +464,30 @@ class RelationshipManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
|
456
464
|
if hidden is not None:
|
|
457
465
|
queryset = queryset.filter(source_hidden=hidden)
|
|
458
466
|
cache.set(cache_key, queryset)
|
|
467
|
+
if not get_queryset:
|
|
468
|
+
listing = list(queryset)
|
|
469
|
+
cache.set(list_cache_key, listing)
|
|
470
|
+
return listing
|
|
459
471
|
return queryset
|
|
460
472
|
|
|
461
473
|
get_for_model_source.cache_key_prefix = "nautobot.extras.relationship.get_for_model_source"
|
|
462
474
|
|
|
463
|
-
def get_for_model_destination(self, model, hidden=None):
|
|
475
|
+
def get_for_model_destination(self, model, hidden=None, get_queryset=True):
|
|
464
476
|
"""
|
|
465
477
|
Return all Relationships assigned to the given model for the destination side only.
|
|
466
478
|
|
|
467
479
|
Args:
|
|
468
480
|
model (Model): The django model to which relationships are registered
|
|
469
481
|
hidden (bool): Filter based on the value of the hidden flag, or None to not apply this filter
|
|
482
|
+
get_queryset (bool): Whether to return a queryset or an object list.
|
|
470
483
|
"""
|
|
471
484
|
concrete_model = model._meta.concrete_model
|
|
472
485
|
cache_key = f"{self.get_for_model_destination.cache_key_prefix}.{concrete_model._meta.label_lower}.{hidden}"
|
|
486
|
+
list_cache_key = f"{cache_key}.list"
|
|
487
|
+
if not get_queryset:
|
|
488
|
+
listing = cache.get(list_cache_key)
|
|
489
|
+
if listing is not None:
|
|
490
|
+
return listing
|
|
473
491
|
queryset = cache.get(cache_key)
|
|
474
492
|
if queryset is None:
|
|
475
493
|
content_type = ContentType.objects.get_for_model(concrete_model)
|
|
@@ -481,6 +499,10 @@ class RelationshipManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
|
481
499
|
if hidden is not None:
|
|
482
500
|
queryset = queryset.filter(destination_hidden=hidden)
|
|
483
501
|
cache.set(cache_key, queryset)
|
|
502
|
+
if not get_queryset:
|
|
503
|
+
listing = list(queryset)
|
|
504
|
+
cache.set(list_cache_key, listing)
|
|
505
|
+
return listing
|
|
484
506
|
return queryset
|
|
485
507
|
|
|
486
508
|
get_for_model_destination.cache_key_prefix = "nautobot.extras.relationship.get_for_model_destination"
|
|
@@ -495,6 +517,33 @@ class RelationshipManager(BaseManager.from_queryset(RestrictedQuerySet)):
|
|
|
495
517
|
| Q(destination_type=content_type, required_on=RelationshipRequiredSideChoices.DESTINATION_SIDE_REQUIRED)
|
|
496
518
|
)
|
|
497
519
|
|
|
520
|
+
def populate_list_caches(self):
|
|
521
|
+
"""Populate all relevant caches for `get_for_model(..., get_queryset=False)` and related lookups."""
|
|
522
|
+
queryset = self.all().select_related("source_type", "destination_type")
|
|
523
|
+
listings = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
|
|
524
|
+
for rel in queryset:
|
|
525
|
+
listings["source"][f"{rel.source_type.app_label}.{rel.source_type.model}"]["None"].append(rel)
|
|
526
|
+
listings["source"][f"{rel.source_type.app_label}.{rel.source_type.model}"][str(rel.source_hidden)].append(
|
|
527
|
+
rel
|
|
528
|
+
)
|
|
529
|
+
listings["destination"][f"{rel.destination_type.app_label}.{rel.destination_type.model}"]["None"].append(
|
|
530
|
+
rel
|
|
531
|
+
)
|
|
532
|
+
listings["destination"][f"{rel.destination_type.app_label}.{rel.destination_type.model}"][
|
|
533
|
+
str(rel.destination_hidden)
|
|
534
|
+
].append(rel)
|
|
535
|
+
for ct in ContentType.objects.all():
|
|
536
|
+
label = f"{ct.app_label}.{ct.model}"
|
|
537
|
+
for hidden in ["None", "True", "False"]:
|
|
538
|
+
cache.set(
|
|
539
|
+
f"{self.get_for_model_source.cache_key_prefix}.{label}.{hidden}.list",
|
|
540
|
+
listings["source"][label][hidden],
|
|
541
|
+
)
|
|
542
|
+
cache.set(
|
|
543
|
+
f"{self.get_for_model_destination.cache_key_prefix}.{label}.{hidden}.list",
|
|
544
|
+
listings["destination"][label][hidden],
|
|
545
|
+
)
|
|
546
|
+
|
|
498
547
|
|
|
499
548
|
class Relationship(
|
|
500
549
|
ChangeLoggedModel,
|
|
@@ -1,97 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Query</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<table class="table table-hover panel-body attr-table">
|
|
10
|
-
<tr>
|
|
11
|
-
<td>Name</td>
|
|
12
|
-
<td><span>{{ object.name }}</span></td>
|
|
13
|
-
</tr>
|
|
14
|
-
<tr>
|
|
15
|
-
<td>Query</td>
|
|
16
|
-
<td><pre id="query"><code class="language-graphql">{{ object.query }}</code></pre></td>
|
|
17
|
-
</tr>
|
|
18
|
-
<tr>
|
|
19
|
-
<td>Query Variables</td>
|
|
20
|
-
<td><pre>{{ object.variables|render_json }}</pre></td>
|
|
21
|
-
</tr>
|
|
22
|
-
</table>
|
|
23
|
-
</div>
|
|
24
|
-
{% endblock content_left_page %}
|
|
25
|
-
|
|
26
|
-
{% block content_right_page %}
|
|
27
|
-
<div class="panel panel-default">
|
|
28
|
-
<div class="panel-heading">
|
|
29
|
-
<strong>Response</strong>
|
|
30
|
-
<button class="btn btn-primary btn-xs pull-right" onclick="test_query()">Execute</button>
|
|
31
|
-
</div>
|
|
32
|
-
{% if object.variables %}
|
|
33
|
-
<table class="table table-hover panel-body attr-table">
|
|
34
|
-
<tr>
|
|
35
|
-
<td>Variables:</td>
|
|
36
|
-
<td><textarea id="query_variables" class="form-control">{{ object.variables|render_json:False }}</textarea></td>
|
|
37
|
-
</tr>
|
|
38
|
-
</table>
|
|
39
|
-
{% endif %}
|
|
40
|
-
<div class="panel-footer">
|
|
41
|
-
<pre id="query_output">
|
|
42
|
-
|
|
43
|
-
</pre>
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
{% endblock content_right_page %}
|
|
47
|
-
|
|
48
|
-
{% block javascript %}
|
|
49
|
-
{{ block.super }}
|
|
50
|
-
<script>
|
|
51
|
-
function fillQueryOutput(data) {
|
|
52
|
-
const queryOutput = document.querySelector('#query_output');
|
|
53
|
-
|
|
54
|
-
[...queryOutput.childNodes].forEach(childNode => childNode.remove());
|
|
55
|
-
|
|
56
|
-
const code = document.createElement('code');
|
|
57
|
-
code.classList.add('language-json');
|
|
58
|
-
code.textContent = JSON.stringify(data, undefined, 2);
|
|
59
|
-
|
|
60
|
-
queryOutput.appendChild(code);
|
|
61
|
-
|
|
62
|
-
hljs.highlightElement(code);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function test_query() {
|
|
66
|
-
const variables = document.querySelector('#query_variables')?.value;
|
|
67
|
-
|
|
68
|
-
$.ajax({
|
|
69
|
-
url: "{% url 'graphql' %}",
|
|
70
|
-
method: "POST",
|
|
71
|
-
headers: {"X-CSRFTOKEN": "{{ csrf_token }}"},
|
|
72
|
-
dataType: "json",
|
|
73
|
-
data: {
|
|
74
|
-
"query": `{{ object.query | escapejs }}`,
|
|
75
|
-
"variables": variables,
|
|
76
|
-
},
|
|
77
|
-
success: function(data) {
|
|
78
|
-
fillQueryOutput(data);
|
|
79
|
-
},
|
|
80
|
-
error: function(error) {
|
|
81
|
-
console.log(error);
|
|
82
|
-
fillQueryOutput(error.responseJSON);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
textarea = document.querySelector("#query_variables");
|
|
88
|
-
textarea.addEventListener('input', autoResize, false);
|
|
89
|
-
textarea.style.height = 'auto';
|
|
90
|
-
textarea.style.height = textarea.scrollHeight + 'px';
|
|
91
|
-
|
|
92
|
-
function autoResize() {
|
|
93
|
-
this.style.height = 'auto';
|
|
94
|
-
this.style.height = this.scrollHeight + 'px';
|
|
95
|
-
}
|
|
96
|
-
</script>
|
|
97
|
-
{% endblock javascript %}
|
|
1
|
+
{% extends 'extras/graphqlquery_retrieve.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{% extends "generic/object_list.html" %}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
+
{% load helpers %}
|
|
3
|
+
|
|
4
|
+
{% block content_left_page %}
|
|
5
|
+
<div class="panel panel-default">
|
|
6
|
+
<div class="panel-heading">
|
|
7
|
+
<strong>Query</strong>
|
|
8
|
+
</div>
|
|
9
|
+
<table class="table table-hover panel-body attr-table">
|
|
10
|
+
<tr>
|
|
11
|
+
<td>Name</td>
|
|
12
|
+
<td><span>{{ object.name }}</span></td>
|
|
13
|
+
</tr>
|
|
14
|
+
<tr>
|
|
15
|
+
<td>Query</td>
|
|
16
|
+
<td><pre id="query"><code class="language-graphql">{{ object.query }}</code></pre></td>
|
|
17
|
+
</tr>
|
|
18
|
+
<tr>
|
|
19
|
+
<td>Query Variables</td>
|
|
20
|
+
<td><pre>{{ object.variables|render_json }}</pre></td>
|
|
21
|
+
</tr>
|
|
22
|
+
</table>
|
|
23
|
+
</div>
|
|
24
|
+
{% endblock content_left_page %}
|
|
25
|
+
|
|
26
|
+
{% block content_right_page %}
|
|
27
|
+
<div class="panel panel-default">
|
|
28
|
+
<div class="panel-heading">
|
|
29
|
+
<strong>Response</strong>
|
|
30
|
+
<button class="btn btn-primary btn-xs pull-right" onclick="test_query()">Execute</button>
|
|
31
|
+
</div>
|
|
32
|
+
{% if object.variables %}
|
|
33
|
+
<table class="table table-hover panel-body attr-table">
|
|
34
|
+
<tr>
|
|
35
|
+
<td>Variables:</td>
|
|
36
|
+
<td><textarea id="query_variables" class="form-control">{{ object.variables|render_json:False }}</textarea></td>
|
|
37
|
+
</tr>
|
|
38
|
+
</table>
|
|
39
|
+
{% endif %}
|
|
40
|
+
<div class="panel-footer">
|
|
41
|
+
<pre id="query_output">
|
|
42
|
+
|
|
43
|
+
</pre>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
{% endblock content_right_page %}
|
|
47
|
+
|
|
48
|
+
{% block javascript %}
|
|
49
|
+
{{ block.super }}
|
|
50
|
+
<script>
|
|
51
|
+
function fillQueryOutput(data) {
|
|
52
|
+
const queryOutput = document.querySelector('#query_output');
|
|
53
|
+
|
|
54
|
+
[...queryOutput.childNodes].forEach(childNode => childNode.remove());
|
|
55
|
+
|
|
56
|
+
const code = document.createElement('code');
|
|
57
|
+
code.classList.add('language-json');
|
|
58
|
+
code.textContent = JSON.stringify(data, undefined, 2);
|
|
59
|
+
|
|
60
|
+
queryOutput.appendChild(code);
|
|
61
|
+
|
|
62
|
+
hljs.highlightElement(code);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function test_query() {
|
|
66
|
+
const variables = document.querySelector('#query_variables')?.value;
|
|
67
|
+
|
|
68
|
+
$.ajax({
|
|
69
|
+
url: "{% url 'graphql' %}",
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: {"X-CSRFTOKEN": "{{ csrf_token }}"},
|
|
72
|
+
dataType: "json",
|
|
73
|
+
data: {
|
|
74
|
+
"query": `{{ object.query | escapejs }}`,
|
|
75
|
+
"variables": variables,
|
|
76
|
+
},
|
|
77
|
+
success: function(data) {
|
|
78
|
+
fillQueryOutput(data);
|
|
79
|
+
},
|
|
80
|
+
error: function(error) {
|
|
81
|
+
console.log(error);
|
|
82
|
+
fillQueryOutput(error.responseJSON);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
textarea = document.querySelector("#query_variables");
|
|
88
|
+
textarea.addEventListener('input', autoResize, false);
|
|
89
|
+
textarea.style.height = 'auto';
|
|
90
|
+
textarea.style.height = textarea.scrollHeight + 'px';
|
|
91
|
+
|
|
92
|
+
function autoResize() {
|
|
93
|
+
this.style.height = 'auto';
|
|
94
|
+
this.style.height = this.scrollHeight + 'px';
|
|
95
|
+
}
|
|
96
|
+
</script>
|
|
97
|
+
{% endblock javascript %}
|
|
@@ -1,29 +1,2 @@
|
|
|
1
|
-
{% extends "
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Secrets Group</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<table class="table table-hover panel-body attr-table">
|
|
10
|
-
<tr>
|
|
11
|
-
<td>Description</td>
|
|
12
|
-
<td colspan="3">{{ object.description | placeholder }}</td>
|
|
13
|
-
</tr>
|
|
14
|
-
<tr>
|
|
15
|
-
<td rowspan="{{ secrets_group_associations | length | add:'1'}}">Secrets</td>
|
|
16
|
-
<th>Access Type</th>
|
|
17
|
-
<th>Secret Type</th>
|
|
18
|
-
<th>Secret</th>
|
|
19
|
-
</tr>
|
|
20
|
-
{% for secret_association in secrets_group_associations %}
|
|
21
|
-
<tr>
|
|
22
|
-
<td>{{ secret_association.access_type }}</td>
|
|
23
|
-
<td>{{ secret_association.secret_type | bettertitle }}</td>
|
|
24
|
-
<td>{{ secret_association.secret|hyperlinked_object }}</td>
|
|
25
|
-
</tr>
|
|
26
|
-
{% endfor %}
|
|
27
|
-
</table>
|
|
28
|
-
</div>
|
|
29
|
-
{% endblock content_left_page %}
|
|
1
|
+
{% extends "extras/secretsgroup_retrieve.html" %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|