nautobot 2.4.13__py3-none-any.whl → 2.4.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/choices.py +8 -0
- nautobot/apps/ui.py +14 -0
- nautobot/core/api/views.py +2 -0
- nautobot/core/choices.py +4 -0
- nautobot/core/filters.py +21 -41
- nautobot/core/graphql/generators.py +8 -0
- nautobot/core/graphql/schema.py +30 -30
- nautobot/core/management/commands/check_job_approval_status.py +47 -0
- nautobot/core/management/commands/generate_test_data.py +1 -1
- nautobot/core/management/commands/migrate.py +90 -1
- nautobot/core/models/tree_queries.py +17 -0
- nautobot/core/settings.py +2 -2
- nautobot/core/settings.yaml +3 -3
- nautobot/core/tables.py +29 -6
- nautobot/core/templates/base_django.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/generic/object_list.html +17 -20
- nautobot/core/templates/inc/breadcrumbs.html +14 -0
- nautobot/core/templatetags/buttons.py +2 -4
- nautobot/core/templatetags/helpers.py +29 -6
- nautobot/core/templatetags/ui_framework.py +21 -0
- nautobot/core/testing/api.py +7 -0
- nautobot/core/testing/filters.py +20 -3
- nautobot/core/testing/forms.py +1 -1
- nautobot/core/tests/integration/test_filters.py +2 -2
- nautobot/core/tests/test_breadcrumbs.py +366 -0
- nautobot/core/tests/test_commands.py +40 -0
- nautobot/core/tests/test_filters.py +51 -1
- nautobot/core/tests/test_forms.py +1 -1
- nautobot/core/tests/test_graphql.py +4 -4
- nautobot/core/tests/test_titles.py +183 -0
- nautobot/core/tests/test_tree_queries.py +30 -0
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/tests/test_views_utils.py +1 -1
- nautobot/core/ui/breadcrumbs.py +538 -0
- nautobot/core/ui/bulk_buttons.py +53 -0
- nautobot/core/ui/object_detail.py +31 -8
- nautobot/core/ui/titles.py +127 -0
- nautobot/core/ui/utils.py +25 -0
- nautobot/core/utils/migrations.py +1 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/mixins.py +26 -1
- nautobot/core/views/renderers.py +20 -2
- nautobot/core/views/utils.py +14 -13
- nautobot/dcim/api/serializers.py +9 -0
- nautobot/dcim/choices.py +55 -0
- nautobot/dcim/constants.py +0 -16
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/filters/__init__.py +15 -3
- nautobot/dcim/forms.py +120 -7
- nautobot/dcim/management/commands/trace_paths.py +1 -1
- nautobot/dcim/migrations/0072_alter_powerfeed_options_and_more.py +97 -0
- nautobot/dcim/models/device_component_templates.py +8 -0
- nautobot/dcim/models/device_components.py +31 -12
- nautobot/dcim/models/devices.py +1 -1
- nautobot/dcim/models/power.py +171 -10
- nautobot/dcim/models/racks.py +7 -4
- nautobot/dcim/tables/devices.py +2 -0
- nautobot/dcim/tables/devicetypes.py +1 -0
- nautobot/dcim/tables/power.py +30 -2
- nautobot/dcim/templates/dcim/device.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -214
- nautobot/dcim/templates/dcim/location_retrieve.html +2 -2
- nautobot/dcim/templates/dcim/powerfeed_edit.html +8 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -1
- nautobot/dcim/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/tests/integration/test_device_bulk_operations.py +61 -0
- nautobot/dcim/tests/test_api.py +24 -4
- nautobot/dcim/tests/test_filters.py +91 -13
- nautobot/dcim/tests/test_models.py +262 -0
- nautobot/dcim/tests/test_views.py +20 -12
- nautobot/dcim/urls.py +2 -27
- nautobot/dcim/utils.py +13 -30
- nautobot/dcim/views.py +428 -146
- nautobot/extras/choices.py +12 -4
- nautobot/extras/factory.py +19 -20
- nautobot/extras/filters/__init__.py +3 -2
- nautobot/extras/filters/mixins.py +23 -7
- nautobot/extras/forms/__init__.py +2 -1
- nautobot/extras/forms/forms.py +71 -0
- nautobot/extras/forms/mixins.py +4 -2
- nautobot/extras/managers.py +4 -1
- 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/migrations/0125_jobresult_date_started.py +18 -0
- nautobot/extras/models/customfields.py +53 -5
- nautobot/extras/models/datasources.py +1 -2
- nautobot/extras/models/jobs.py +13 -3
- nautobot/extras/models/relationships.py +55 -6
- nautobot/extras/plugins/views.py +24 -1
- nautobot/extras/secrets/__init__.py +1 -1
- nautobot/extras/tables.py +9 -0
- nautobot/extras/templates/extras/customfield.html +2 -129
- nautobot/extras/templates/extras/customfield_edit.html +2 -108
- nautobot/extras/templates/extras/customfield_retrieve.html +129 -0
- nautobot/extras/templates/extras/customfield_update.html +108 -0
- nautobot/extras/templates/extras/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/inc/jobresult.html +7 -3
- nautobot/extras/templates/extras/jobresult.html +2 -155
- nautobot/extras/templates/extras/jobresult_retrieve.html +155 -0
- nautobot/extras/templates/extras/marketplace.html +5 -6
- nautobot/extras/templates/extras/note.html +2 -53
- nautobot/extras/templates/extras/note_retrieve.html +53 -0
- nautobot/extras/templates/extras/plugins_list.html +5 -6
- nautobot/extras/templates/extras/secretsgroup.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/templatetags/custom_links.py +2 -2
- nautobot/extras/templatetags/job_buttons.py +1 -1
- nautobot/extras/templatetags/plugins.py +1 -1
- nautobot/extras/tests/integration/test_computedfields.py +2 -2
- nautobot/extras/tests/integration/test_customfields.py +14 -11
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_notes.py +1 -1
- nautobot/extras/tests/integration/test_plugins.py +6 -6
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_customfields.py +115 -7
- nautobot/extras/tests/test_filters.py +9 -0
- nautobot/extras/tests/test_forms.py +2 -2
- nautobot/extras/tests/test_plugins.py +2 -3
- nautobot/extras/tests/test_relationships.py +14 -8
- nautobot/extras/tests/test_views.py +285 -2
- nautobot/extras/urls.py +5 -110
- nautobot/extras/utils.py +5 -2
- nautobot/extras/views.py +116 -311
- nautobot/ipam/api/views.py +69 -6
- nautobot/ipam/tables.py +8 -15
- nautobot/ipam/tests/migration/test_migrations.py +8 -8
- nautobot/ipam/tests/test_api.py +352 -2
- nautobot/ipam/tests/test_models.py +1 -1
- nautobot/project-static/docs/404.html +34 -34
- nautobot/project-static/docs/apps/index.html +34 -34
- nautobot/project-static/docs/apps/nautobot-apps.html +34 -34
- nautobot/project-static/docs/assets/_mkdocstrings.css +44 -6
- 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 +39 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +139 -54
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +48 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +50 -40
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +35 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +43 -39
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +52 -42
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +50 -41
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +54 -44
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +85 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +154 -62
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +54 -46
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +146 -87
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +240 -70
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +38 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +41 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +173 -52
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +269 -85
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5987 -2643
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +165 -89
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +161 -69
- nautobot/project-static/docs/development/apps/api/configuration-view.html +34 -34
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/global-search.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/graphql.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +34 -34
- nautobot/project-static/docs/development/apps/api/prometheus.html +34 -34
- nautobot/project-static/docs/development/apps/api/setup.html +34 -34
- nautobot/project-static/docs/development/apps/api/testing.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/base-template.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +42 -36
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/notes.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/urls.html +34 -34
- nautobot/project-static/docs/development/apps/index.html +34 -34
- nautobot/project-static/docs/development/apps/migration/code-updates.html +34 -34
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +34 -34
- nautobot/project-static/docs/development/apps/migration/from-v1.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +37 -37
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +10544 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +34 -34
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +37 -37
- nautobot/project-static/docs/development/core/application-registry.html +162 -133
- nautobot/project-static/docs/development/core/best-practices.html +34 -34
- nautobot/project-static/docs/development/core/bootstrap-ui.html +34 -34
- nautobot/project-static/docs/development/core/caching.html +34 -34
- nautobot/project-static/docs/development/core/controllers.html +34 -34
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +34 -34
- nautobot/project-static/docs/development/core/generic-views.html +34 -34
- nautobot/project-static/docs/development/core/getting-started.html +34 -34
- nautobot/project-static/docs/development/core/homepage.html +34 -34
- nautobot/project-static/docs/development/core/index.html +34 -34
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +34 -34
- nautobot/project-static/docs/development/core/model-checklist.html +34 -34
- nautobot/project-static/docs/development/core/model-features.html +34 -34
- nautobot/project-static/docs/development/core/natural-keys.html +34 -34
- nautobot/project-static/docs/development/core/navigation-menu.html +34 -34
- nautobot/project-static/docs/development/core/release-checklist.html +34 -34
- nautobot/project-static/docs/development/core/role-internals.html +34 -34
- nautobot/project-static/docs/development/core/settings.html +34 -34
- nautobot/project-static/docs/development/core/style-guide.html +34 -34
- nautobot/project-static/docs/development/core/templates.html +34 -34
- nautobot/project-static/docs/development/core/testing.html +34 -34
- nautobot/project-static/docs/development/core/ui-component-framework.html +724 -289
- nautobot/project-static/docs/development/core/user-preferences.html +34 -34
- nautobot/project-static/docs/development/index.html +34 -34
- nautobot/project-static/docs/development/jobs/getting-started.html +34 -34
- nautobot/project-static/docs/development/jobs/index.html +34 -34
- nautobot/project-static/docs/development/jobs/installation.html +34 -34
- nautobot/project-static/docs/development/jobs/job-extensions.html +34 -34
- nautobot/project-static/docs/development/jobs/job-logging.html +34 -34
- nautobot/project-static/docs/development/jobs/job-patterns.html +34 -34
- nautobot/project-static/docs/development/jobs/job-structure.html +34 -34
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +34 -34
- nautobot/project-static/docs/development/jobs/testing.html +34 -34
- nautobot/project-static/docs/index.html +34 -34
- nautobot/project-static/docs/media/development/core/ui-component-framework/breadcrumbs-titles-data-flow.png +0 -0
- nautobot/project-static/docs/media/power_distribution.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +34 -34
- nautobot/project-static/docs/overview/design_philosophy.html +34 -34
- nautobot/project-static/docs/release-notes/index.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.0.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.1.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.2.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.3.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.4.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.5.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.6.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.0.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.1.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.2.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.3.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.4.html +402 -34
- nautobot/project-static/docs/requirements.txt +3 -3
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +37 -37
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/services.html +34 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +34 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +34 -34
- nautobot/project-static/docs/user-guide/administration/security/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/security/notices.html +34 -34
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +296 -251
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +37 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +42 -52
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +316 -39
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +35 -35
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +147 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +52 -35
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +51 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +34 -34
- nautobot/project-static/docs/user-guide/index.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +35 -35
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +34 -34
- nautobot/tenancy/api/views.py +2 -1
- nautobot/users/tests/test_api.py +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -252
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -75
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +252 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +75 -0
- nautobot/virtualization/urls.py +3 -61
- nautobot/virtualization/views.py +48 -72
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/METADATA +27 -27
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/RECORD +463 -439
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/NOTICE +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/WHEEL +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/entry_points.txt +0 -0
nautobot/core/tables.py
CHANGED
|
@@ -5,7 +5,7 @@ from django.conf import settings
|
|
|
5
5
|
from django.contrib.auth.models import AnonymousUser
|
|
6
6
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
7
7
|
from django.core.exceptions import FieldDoesNotExist, FieldError
|
|
8
|
-
from django.db.models import Prefetch
|
|
8
|
+
from django.db.models import Prefetch, QuerySet
|
|
9
9
|
from django.db.models.fields.related import ForeignKey, RelatedField
|
|
10
10
|
from django.db.models.fields.reverse_related import ManyToOneRel
|
|
11
11
|
from django.urls import reverse
|
|
@@ -80,14 +80,14 @@ class BaseTable(django_tables2.Table):
|
|
|
80
80
|
reverse_lookup="static_group_associations__associated_object_id",
|
|
81
81
|
)
|
|
82
82
|
|
|
83
|
-
for cf in models.CustomField.objects.get_for_model(model):
|
|
83
|
+
for cf in models.CustomField.objects.get_for_model(model, get_queryset=False):
|
|
84
84
|
name = cf.add_prefix_to_cf_key()
|
|
85
85
|
self.base_columns[name] = CustomFieldColumn(cf)
|
|
86
86
|
|
|
87
|
-
for cpf in models.ComputedField.objects.get_for_model(model):
|
|
87
|
+
for cpf in models.ComputedField.objects.get_for_model(model, get_queryset=False):
|
|
88
88
|
self.base_columns[f"cpf_{cpf.key}"] = ComputedFieldColumn(cpf)
|
|
89
89
|
|
|
90
|
-
for relationship in models.Relationship.objects.get_for_model_source(model):
|
|
90
|
+
for relationship in models.Relationship.objects.get_for_model_source(model, get_queryset=False):
|
|
91
91
|
if not relationship.symmetric:
|
|
92
92
|
self.base_columns[f"cr_{relationship.key}_src"] = RelationshipColumn(
|
|
93
93
|
relationship, side=choices.RelationshipSideChoices.SIDE_SOURCE
|
|
@@ -97,7 +97,7 @@ class BaseTable(django_tables2.Table):
|
|
|
97
97
|
relationship, side=choices.RelationshipSideChoices.SIDE_PEER
|
|
98
98
|
)
|
|
99
99
|
|
|
100
|
-
for relationship in models.Relationship.objects.get_for_model_destination(model):
|
|
100
|
+
for relationship in models.Relationship.objects.get_for_model_destination(model, get_queryset=False):
|
|
101
101
|
if not relationship.symmetric:
|
|
102
102
|
self.base_columns[f"cr_{relationship.key}_dst"] = RelationshipColumn(
|
|
103
103
|
relationship, side=choices.RelationshipSideChoices.SIDE_DESTINATION
|
|
@@ -333,6 +333,29 @@ class BaseTable(django_tables2.Table):
|
|
|
333
333
|
# Otherwise, use the default sorting method
|
|
334
334
|
self.data.order_by(self._order_by)
|
|
335
335
|
|
|
336
|
+
def add_conditional_prefetch(self, table_field, db_column=None, prefetch=None):
|
|
337
|
+
"""Conditionally prefetch the specified database column if the related table field is visible.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
table_field (str): Name of the field on the table to check for visibility. Also used as the prefetch field
|
|
341
|
+
if neither db_column nor prefetch is specified.
|
|
342
|
+
db_column (str): Optionally specify the db column to prefetch. Mutually exclusive with prefetch.
|
|
343
|
+
prefetch (Prefetch): Optionally specify a prefetch object. Mutually exclusive with db_column.
|
|
344
|
+
"""
|
|
345
|
+
if db_column and prefetch:
|
|
346
|
+
raise ValueError(
|
|
347
|
+
"BaseTable.add_conditional_prefetch called with both db_column and prefetch, this is not allowed."
|
|
348
|
+
)
|
|
349
|
+
if not db_column:
|
|
350
|
+
db_column = table_field
|
|
351
|
+
if table_field in self.columns and self.columns[table_field].visible and isinstance(self.data.data, QuerySet):
|
|
352
|
+
if prefetch:
|
|
353
|
+
self.data = TableData.from_data(self.data.data.prefetch_related(prefetch))
|
|
354
|
+
else:
|
|
355
|
+
self.data = TableData.from_data(self.data.data.prefetch_related(db_column))
|
|
356
|
+
self.data.set_table(self)
|
|
357
|
+
self.rows = BoundRows(data=self.data, table=self, pinned_data=self.pinned_data)
|
|
358
|
+
|
|
336
359
|
|
|
337
360
|
#
|
|
338
361
|
# Table columns
|
|
@@ -353,7 +376,7 @@ class ToggleColumn(django_tables2.CheckBoxColumn):
|
|
|
353
376
|
|
|
354
377
|
@property
|
|
355
378
|
def header(self):
|
|
356
|
-
return mark_safe('<input type="checkbox" class="toggle" title="Toggle all" />')
|
|
379
|
+
return mark_safe('<input type="checkbox" class="toggle" title="Toggle all" />')
|
|
357
380
|
|
|
358
381
|
|
|
359
382
|
class BooleanColumn(django_tables2.Column):
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<!DOCTYPE html>
|
|
6
6
|
<html lang="en"{% if request.COOKIES|get_item:"theme" == 'dark' %} data-theme="dark"{% endif %}>
|
|
7
7
|
<head>
|
|
8
|
-
<title>{% block title %}Home{% endblock %} - {{ settings.BRANDING_TITLE }}</title>
|
|
8
|
+
<title>{% block title %}Home{% endblock %}{% block document_title_extra %}{% endblock %} - {{ settings.BRANDING_TITLE }}</title>
|
|
9
9
|
{% include 'inc/media.html' %}
|
|
10
10
|
{% block extra_styles %}{% endblock %}
|
|
11
11
|
</head>
|
|
@@ -4,18 +4,26 @@
|
|
|
4
4
|
{% load perms %}
|
|
5
5
|
{% load plugins %}
|
|
6
6
|
{% load static %}
|
|
7
|
+
{% load ui_framework %}
|
|
8
|
+
|
|
9
|
+
{% block document_title_extra %}{% saved_view_title "plain" %}{% endblock %}
|
|
7
10
|
|
|
8
11
|
{% block header %}
|
|
9
12
|
<div class="row noprint">
|
|
10
13
|
<div class="{% if search_form %}col-sm-8 col-md-9 {% else %} col-md-12 {% endif %}">
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
{% if breadcrumbs is not None %}
|
|
15
|
+
{% render_breadcrumbs %}
|
|
16
|
+
{% else %}
|
|
17
|
+
{# TODO: remove this fragment after breadcrumbs implementation in generic views like ConsoleConnectionsListView #}
|
|
18
|
+
<ol class="breadcrumb">
|
|
19
|
+
{% block breadcrumbs %}
|
|
20
|
+
{% if list_url %}
|
|
21
|
+
<li><a href="{% url list_url %}">{{ title }}</a></li>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% block extra_breadcrumbs %}{% endblock extra_breadcrumbs %}
|
|
24
|
+
{% endblock breadcrumbs %}
|
|
25
|
+
</ol>
|
|
26
|
+
{% endif %}
|
|
19
27
|
</div>
|
|
20
28
|
{% if search_form %}
|
|
21
29
|
<div class="col-sm-4 col-md-3">
|
|
@@ -146,18 +154,7 @@
|
|
|
146
154
|
{% endblock export_button %}
|
|
147
155
|
{% endif %}
|
|
148
156
|
</div>
|
|
149
|
-
<h1>{% block title %}
|
|
150
|
-
{{ title }}
|
|
151
|
-
{% if current_saved_view %}
|
|
152
|
-
—
|
|
153
|
-
{% if new_changes_not_applied %}
|
|
154
|
-
<i title="Pending changes not saved">{{ current_saved_view.name }}</i>
|
|
155
|
-
{% else %}
|
|
156
|
-
{{ current_saved_view.name }}
|
|
157
|
-
{% endif %}
|
|
158
|
-
{% endif %}
|
|
159
|
-
{% endblock %}
|
|
160
|
-
</h1>
|
|
157
|
+
<h1>{% block title %}{% render_title %}{% endblock %}{% saved_view_title %}</h1>
|
|
161
158
|
{% block header_extra %}{% endblock %}
|
|
162
159
|
{% if filter_params %}
|
|
163
160
|
<div class="filters-applied">
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<ol class="breadcrumb">
|
|
2
|
+
{% block breadcrumbs %}
|
|
3
|
+
{% for url, title in breadcrumbs_items %}
|
|
4
|
+
<li>
|
|
5
|
+
{% if url %}
|
|
6
|
+
<a href="{{ url }}">{{ title }}</a>
|
|
7
|
+
{% else %}
|
|
8
|
+
{{ title }}
|
|
9
|
+
{% endif %}
|
|
10
|
+
</li>
|
|
11
|
+
{% endfor %}
|
|
12
|
+
{% block extra_breadcrumbs %}{% endblock extra_breadcrumbs %}
|
|
13
|
+
{% endblock %}
|
|
14
|
+
</ol>
|
|
@@ -176,8 +176,6 @@ def consolidate_bulk_action_buttons(context):
|
|
|
176
176
|
"bulk_action_buttons": bulk_action_buttons,
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
params = ("?" + context["request"].GET.urlencode()) if context["request"].GET else ""
|
|
180
|
-
|
|
181
179
|
primary_button_fragment = child_button_fragment = """
|
|
182
180
|
<button {attrs}>
|
|
183
181
|
<span class="{icon}" aria-hidden="true"></span> {label}
|
|
@@ -203,7 +201,7 @@ def consolidate_bulk_action_buttons(context):
|
|
|
203
201
|
attrs=render_tag_attrs(
|
|
204
202
|
{
|
|
205
203
|
"class": edit_button_classes,
|
|
206
|
-
"formaction": reverse(context["bulk_edit_url"])
|
|
204
|
+
"formaction": reverse(context["bulk_edit_url"]),
|
|
207
205
|
"type": "submit",
|
|
208
206
|
}
|
|
209
207
|
),
|
|
@@ -242,7 +240,7 @@ def consolidate_bulk_action_buttons(context):
|
|
|
242
240
|
"class": delete_button_classes,
|
|
243
241
|
"type": "submit",
|
|
244
242
|
"name": "_delete",
|
|
245
|
-
"formaction": reverse(context["bulk_delete_url"])
|
|
243
|
+
"formaction": reverse(context["bulk_delete_url"]),
|
|
246
244
|
}
|
|
247
245
|
),
|
|
248
246
|
icon="mdi mdi-trash-can-outline",
|
|
@@ -2,6 +2,7 @@ import datetime
|
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
+
from typing import Literal
|
|
5
6
|
from urllib.parse import parse_qs, quote_plus
|
|
6
7
|
|
|
7
8
|
from django import template
|
|
@@ -12,7 +13,7 @@ from django.contrib.staticfiles.finders import find
|
|
|
12
13
|
from django.core.exceptions import ObjectDoesNotExist
|
|
13
14
|
from django.templatetags.static import static, StaticNode
|
|
14
15
|
from django.urls import NoReverseMatch, reverse
|
|
15
|
-
from django.utils.html import format_html, format_html_join
|
|
16
|
+
from django.utils.html import format_html, format_html_join, strip_tags
|
|
16
17
|
from django.utils.safestring import mark_safe
|
|
17
18
|
from django.utils.text import slugify as django_slugify
|
|
18
19
|
from django_jinja import library
|
|
@@ -25,10 +26,9 @@ from nautobot.core.constants import PAGINATE_COUNT_DEFAULT
|
|
|
25
26
|
from nautobot.core.utils import color, config, data, logging as nautobot_logging, lookup
|
|
26
27
|
from nautobot.core.utils.requests import add_nautobot_version_query_param_to_url
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
HTML_NONE = mark_safe('<span class="text-muted">—</span>') # noqa: S308
|
|
29
|
+
HTML_TRUE = mark_safe('<span class="text-success"><i class="mdi mdi-check-bold" title="Yes"></i></span>')
|
|
30
|
+
HTML_FALSE = mark_safe('<span class="text-danger"><i class="mdi mdi-close-thick" title="No"></i></span>')
|
|
31
|
+
HTML_NONE = mark_safe('<span class="text-muted">—</span>')
|
|
32
32
|
|
|
33
33
|
DEFAULT_SUPPORT_MESSAGE = (
|
|
34
34
|
"If further assistance is required, please join the `#nautobot` channel "
|
|
@@ -1124,7 +1124,7 @@ def custom_branding_or_static(branding_asset, static_asset):
|
|
|
1124
1124
|
branding has been configured in settings, else it returns stock branding via static.
|
|
1125
1125
|
"""
|
|
1126
1126
|
if settings.BRANDING_FILEPATHS.get(branding_asset):
|
|
1127
|
-
url = f"{
|
|
1127
|
+
url = f"{settings.MEDIA_URL}{settings.BRANDING_FILEPATHS.get(branding_asset)}"
|
|
1128
1128
|
else:
|
|
1129
1129
|
url = StaticNode.handle_simple(static_asset)
|
|
1130
1130
|
return add_nautobot_version_query_param_to_url(url)
|
|
@@ -1255,3 +1255,26 @@ def _build_hyperlink(value, field="", target="", rel=""):
|
|
|
1255
1255
|
except AttributeError:
|
|
1256
1256
|
pass
|
|
1257
1257
|
return format_html("{}", display)
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
@register.simple_tag(takes_context=True)
|
|
1261
|
+
def saved_view_title(context, mode: Literal["html", "plain"] = "html"):
|
|
1262
|
+
"""
|
|
1263
|
+
Creates a formatted title that includes saved view information.
|
|
1264
|
+
Usage: <h1>{{ title }}{% saved_view_title "html" %}</h1>
|
|
1265
|
+
"""
|
|
1266
|
+
new_changes_not_applied = context.get("new_changes_not_applied", False)
|
|
1267
|
+
current_saved_view = context.get("current_saved_view")
|
|
1268
|
+
|
|
1269
|
+
if not current_saved_view:
|
|
1270
|
+
return ""
|
|
1271
|
+
|
|
1272
|
+
if new_changes_not_applied:
|
|
1273
|
+
title = format_html(' — <i title="Pending changes not saved">{}</i>', current_saved_view.name)
|
|
1274
|
+
else:
|
|
1275
|
+
title = format_html(" — {}", current_saved_view.name)
|
|
1276
|
+
|
|
1277
|
+
if mode == "plain":
|
|
1278
|
+
return strip_tags(title)
|
|
1279
|
+
|
|
1280
|
+
return title
|
|
@@ -3,6 +3,8 @@ import logging
|
|
|
3
3
|
from django import template
|
|
4
4
|
from django.utils.html import format_html_join
|
|
5
5
|
|
|
6
|
+
from nautobot.core.ui.breadcrumbs import Breadcrumbs
|
|
7
|
+
from nautobot.core.ui.titles import Titles
|
|
6
8
|
from nautobot.core.utils.lookup import get_view_for_model
|
|
7
9
|
from nautobot.core.views.utils import get_obj_from_context
|
|
8
10
|
|
|
@@ -27,6 +29,25 @@ def render_components(context, components):
|
|
|
27
29
|
return ""
|
|
28
30
|
|
|
29
31
|
|
|
32
|
+
@register.simple_tag(takes_context=True)
|
|
33
|
+
def render_title(context, mode="plain"):
|
|
34
|
+
title_obj = context.get("view_titles")
|
|
35
|
+
if title_obj is not None and isinstance(title_obj, Titles):
|
|
36
|
+
return title_obj.render(context, mode=mode)
|
|
37
|
+
|
|
38
|
+
if fallback_title := context.get("title"):
|
|
39
|
+
return fallback_title
|
|
40
|
+
return ""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@register.simple_tag(takes_context=True)
|
|
44
|
+
def render_breadcrumbs(context):
|
|
45
|
+
breadcrumbs_obj = context.get("breadcrumbs")
|
|
46
|
+
if breadcrumbs_obj is not None and isinstance(breadcrumbs_obj, Breadcrumbs):
|
|
47
|
+
return breadcrumbs_obj.render(context)
|
|
48
|
+
return ""
|
|
49
|
+
|
|
50
|
+
|
|
30
51
|
@register.simple_tag(takes_context=True)
|
|
31
52
|
def render_detail_view_extra_buttons(context):
|
|
32
53
|
"""
|
nautobot/core/testing/api.py
CHANGED
|
@@ -7,6 +7,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey
|
|
|
7
7
|
from django.contrib.contenttypes.models import ContentType
|
|
8
8
|
from django.db import connections, DEFAULT_DB_ALIAS
|
|
9
9
|
from django.db.models import ForeignKey, ManyToManyField, QuerySet
|
|
10
|
+
from django.http import QueryDict
|
|
10
11
|
from django.test import override_settings, tag
|
|
11
12
|
from django.test.utils import CaptureQueriesContext
|
|
12
13
|
from django.urls import reverse
|
|
@@ -105,6 +106,12 @@ class APITestCase(views.ModelTestCase):
|
|
|
105
106
|
m2m_fields.append(field_name)
|
|
106
107
|
return m2m_fields
|
|
107
108
|
|
|
109
|
+
@staticmethod
|
|
110
|
+
def add_query_params_to_url(url: str, query_dict: dict) -> str:
|
|
111
|
+
query = QueryDict(mutable=True)
|
|
112
|
+
query.update(query_dict)
|
|
113
|
+
return f"{url}?{query.urlencode()}"
|
|
114
|
+
|
|
108
115
|
|
|
109
116
|
@tag("unit")
|
|
110
117
|
class APIViewTestCases:
|
nautobot/core/testing/filters.py
CHANGED
|
@@ -15,6 +15,7 @@ from nautobot.core.filters import (
|
|
|
15
15
|
ContentTypeChoiceFilter,
|
|
16
16
|
ContentTypeFilter,
|
|
17
17
|
ContentTypeMultipleChoiceFilter,
|
|
18
|
+
NaturalKeyOrPKMultipleChoiceFilter,
|
|
18
19
|
RelatedMembershipBooleanFilter,
|
|
19
20
|
SearchFilter,
|
|
20
21
|
)
|
|
@@ -207,15 +208,29 @@ class FilterTestCases:
|
|
|
207
208
|
qs_result = self.queryset.filter(**{f"{field_name}__in": test_data}).distinct()
|
|
208
209
|
self.assertQuerysetEqualAndNotEmpty(filterset_result, qs_result, ordered=False)
|
|
209
210
|
|
|
211
|
+
def test_automagic_filters(self):
|
|
212
|
+
"""https://github.com/nautobot/nautobot/issues/6656"""
|
|
213
|
+
self.assertIsNotNone(self.filterset)
|
|
214
|
+
fs = self.filterset() # pylint: disable=not-callable
|
|
215
|
+
if getattr(self.queryset.model, "is_contact_associable_model", False):
|
|
216
|
+
self.assertIsInstance(fs.filters["contacts"], NaturalKeyOrPKMultipleChoiceFilter)
|
|
217
|
+
self.assertIsInstance(fs.filters["contacts__n"], NaturalKeyOrPKMultipleChoiceFilter)
|
|
218
|
+
self.assertIsInstance(fs.filters["teams"], NaturalKeyOrPKMultipleChoiceFilter)
|
|
219
|
+
self.assertIsInstance(fs.filters["teams__n"], NaturalKeyOrPKMultipleChoiceFilter)
|
|
220
|
+
|
|
221
|
+
if getattr(self.queryset.model, "is_dynamic_group_associable_model", False):
|
|
222
|
+
self.assertIsInstance(fs.filters["dynamic_groups"], NaturalKeyOrPKMultipleChoiceFilter)
|
|
223
|
+
self.assertIsInstance(fs.filters["dynamic_groups__n"], NaturalKeyOrPKMultipleChoiceFilter)
|
|
224
|
+
|
|
210
225
|
def test_boolean_filters_generic(self):
|
|
211
|
-
"""Test all `RelatedMembershipBooleanFilter` filters found in `self.filterset.
|
|
226
|
+
"""Test all `RelatedMembershipBooleanFilter` filters found in `self.filterset.filters`
|
|
212
227
|
except for the ones with custom filter logic defined in its `method` attribute.
|
|
213
228
|
|
|
214
229
|
This test asserts that `filter=True` matches `self.queryset.filter(field__isnull=False)` and
|
|
215
230
|
that `filter=False` matches `self.queryset.filter(field__isnull=True)`.
|
|
216
231
|
"""
|
|
217
232
|
self.assertIsNotNone(self.filterset)
|
|
218
|
-
for filter_name, filter_object in self.filterset
|
|
233
|
+
for filter_name, filter_object in self.filterset().filters.items(): # pylint: disable=not-callable
|
|
219
234
|
if not isinstance(filter_object, RelatedMembershipBooleanFilter):
|
|
220
235
|
continue
|
|
221
236
|
if filter_object.method is not None:
|
|
@@ -380,6 +395,8 @@ class FilterTestCases:
|
|
|
380
395
|
self._assert_q_filter_predicate_validity(obj, obj_field_name, filter_field_name, lookup_method)
|
|
381
396
|
|
|
382
397
|
def test_content_type_related_fields_uses_content_type_filter(self):
|
|
398
|
+
self.assertIsNotNone(self.filterset)
|
|
399
|
+
fs = self.filterset() # pylint: disable=not-callable
|
|
383
400
|
for field in self.queryset.model._meta.fields:
|
|
384
401
|
related_model = getattr(field, "related_model", None)
|
|
385
402
|
if not related_model or related_model != ContentType:
|
|
@@ -387,7 +404,7 @@ class FilterTestCases:
|
|
|
387
404
|
with self.subTest(
|
|
388
405
|
f"Assert {self.filterset.__class__.__name__}.{field.name} implements ContentTypeFilter"
|
|
389
406
|
):
|
|
390
|
-
filter_field =
|
|
407
|
+
filter_field = fs.filters.get(field.name)
|
|
391
408
|
if not filter_field:
|
|
392
409
|
# This field is not part of the Filterset.
|
|
393
410
|
continue
|
nautobot/core/testing/forms.py
CHANGED
|
@@ -24,7 +24,7 @@ class FormTestCases:
|
|
|
24
24
|
self.skipTest(f"{self.form_class.__name__}.{field_name} has no query_params")
|
|
25
25
|
field_model = field_class.queryset.model
|
|
26
26
|
filterset_class = get_filterset_for_model(field_model)
|
|
27
|
-
filterset_fields = set(filterset_class
|
|
27
|
+
filterset_fields = set(filterset_class().filters.keys())
|
|
28
28
|
invalid_query_params = query_params_fields - filterset_fields
|
|
29
29
|
self.assertFalse(
|
|
30
30
|
invalid_query_params,
|
|
@@ -148,7 +148,7 @@ class ListViewFilterTestCase(SeleniumTestCase):
|
|
|
148
148
|
|
|
149
149
|
def test_input_field_gets_updated(self):
|
|
150
150
|
"""Assert that a filter input/select field on Dynamic Filter Form updates if same field is updated."""
|
|
151
|
-
self.browser.visit(f
|
|
151
|
+
self.browser.visit(f"{self.live_server_url}{reverse('dcim:location_list')}")
|
|
152
152
|
|
|
153
153
|
text_field_name = self.custom_fields[0].add_prefix_to_cf_key()
|
|
154
154
|
integer_field_name = self.custom_fields[1].add_prefix_to_cf_key()
|
|
@@ -225,7 +225,7 @@ class ListViewFilterTestCase(SeleniumTestCase):
|
|
|
225
225
|
def test_advanced_filter_application(self):
|
|
226
226
|
"""Assert that filters are applied successfully when using the advanced filter."""
|
|
227
227
|
# Go to the location list view
|
|
228
|
-
self.browser.visit(f
|
|
228
|
+
self.browser.visit(f"{self.live_server_url}{reverse('dcim:location_list')}")
|
|
229
229
|
# create a new tag
|
|
230
230
|
tag = Tag.objects.create(name="Tag1")
|
|
231
231
|
tag.content_types.set([ContentType.objects.get_for_model(Location)])
|