nautobot 2.3.16__py3-none-any.whl → 2.4.0b1__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/__init__.py +15 -0
- nautobot/apps/api.py +0 -2
- nautobot/apps/config.py +32 -3
- nautobot/apps/events.py +19 -0
- nautobot/apps/exceptions.py +0 -2
- nautobot/apps/ui.py +44 -9
- nautobot/apps/utils.py +0 -8
- nautobot/apps/views.py +2 -0
- nautobot/circuits/navigation.py +0 -57
- nautobot/circuits/tables.py +1 -2
- nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
- nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
- nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
- nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
- nautobot/circuits/tests/integration/test_relationships.py +33 -24
- nautobot/circuits/tests/test_filters.py +4 -8
- nautobot/circuits/views.py +143 -26
- nautobot/cloud/factory.py +4 -1
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/tests/test_filters.py +5 -4
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/metadata.py +28 -256
- nautobot/core/api/pagination.py +3 -2
- nautobot/core/api/renderers.py +3 -0
- nautobot/core/api/serializers.py +24 -244
- nautobot/core/api/urls.py +3 -4
- nautobot/core/api/utils.py +0 -62
- nautobot/core/api/views.py +48 -158
- nautobot/core/apps/__init__.py +22 -578
- nautobot/core/celery/__init__.py +13 -0
- nautobot/core/celery/log.py +4 -4
- nautobot/core/celery/schedulers.py +48 -3
- nautobot/core/cli/__init__.py +8 -0
- nautobot/core/constants.py +7 -0
- nautobot/core/events/__init__.py +116 -0
- nautobot/core/events/base.py +27 -0
- nautobot/core/events/exceptions.py +10 -0
- nautobot/core/events/redis_broker.py +48 -0
- nautobot/core/events/syslog_broker.py +19 -0
- nautobot/core/exceptions.py +0 -6
- nautobot/core/filters.py +16 -21
- nautobot/core/fixtures/user-data.json +59 -0
- nautobot/core/forms/fields.py +53 -8
- nautobot/core/forms/utils.py +2 -1
- nautobot/core/graphql/schema.py +3 -1
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +4 -4
- nautobot/core/jobs/cleanup.py +13 -49
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/generate_test_data.py +21 -0
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/middleware.py +16 -0
- nautobot/core/models/__init__.py +1 -1
- nautobot/core/models/fields.py +11 -7
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +3 -6
- nautobot/core/settings.py +44 -7
- nautobot/core/settings.yaml +86 -8
- nautobot/core/tables.py +15 -65
- nautobot/core/tasks.py +1 -1
- nautobot/core/templates/components/button/default.html +7 -0
- nautobot/core/templates/components/button/dropdown.html +20 -0
- nautobot/core/templates/components/layout/one_over_two.html +19 -0
- nautobot/core/templates/components/layout/two_over_one.html +19 -0
- nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
- nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
- nautobot/core/templates/components/panel/body_content_tags.html +6 -0
- nautobot/core/templates/components/panel/body_content_text.html +12 -0
- nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
- nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
- nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
- nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
- nautobot/core/templates/components/panel/footer_content_table.html +14 -0
- nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
- nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
- nautobot/core/templates/components/panel/panel.html +16 -0
- nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
- nautobot/core/templates/components/tab/content_wrapper.html +3 -0
- nautobot/core/templates/components/tab/label_wrapper.html +5 -0
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
- nautobot/core/templates/generic/object_retrieve.html +28 -17
- nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
- nautobot/core/templates/inc/custom_fields/panel.html +2 -2
- nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
- nautobot/core/templates/inc/footer.html +1 -0
- nautobot/core/templates/inc/media.html +0 -3
- nautobot/core/templates/inc/nav_menu.html +1 -1
- nautobot/core/templates/inc/relationships_panel.html +1 -1
- nautobot/core/templates/nautobot_config.py.j2 +3 -3
- nautobot/core/templates/panel_table.html +12 -0
- nautobot/core/templates/search.html +0 -7
- nautobot/core/templates/utilities/render_jinja2.html +117 -0
- nautobot/core/templatetags/helpers.py +101 -12
- nautobot/core/templatetags/ui_framework.py +40 -0
- nautobot/core/testing/api.py +23 -128
- nautobot/core/testing/context.py +18 -0
- nautobot/core/testing/filters.py +41 -58
- nautobot/core/testing/mixins.py +2 -7
- nautobot/core/testing/views.py +25 -123
- nautobot/core/tests/integration/test_app_home.py +1 -0
- nautobot/core/tests/integration/test_app_navbar.py +1 -0
- nautobot/core/tests/integration/test_filters.py +2 -0
- nautobot/core/tests/integration/test_home.py +1 -0
- nautobot/core/tests/integration/test_navbar.py +1 -0
- nautobot/core/tests/integration/test_view_authentication.py +1 -2
- nautobot/core/tests/nautobot_config.py +198 -0
- nautobot/core/tests/runner.py +3 -3
- nautobot/core/tests/test_api.py +82 -201
- nautobot/core/tests/test_csv.py +3 -25
- nautobot/core/tests/test_events.py +214 -0
- nautobot/core/tests/test_jinja_filters.py +1 -0
- nautobot/core/tests/test_jobs.py +84 -13
- nautobot/core/tests/test_navigations.py +7 -241
- nautobot/core/tests/test_templatetags_helpers.py +16 -0
- nautobot/core/tests/test_ui.py +150 -0
- nautobot/core/tests/test_utils.py +0 -25
- nautobot/core/tests/test_views.py +123 -31
- nautobot/core/ui/__init__.py +0 -0
- nautobot/core/ui/base.py +11 -0
- nautobot/core/ui/choices.py +44 -0
- nautobot/core/ui/homepage.py +167 -0
- nautobot/core/ui/nav.py +279 -0
- nautobot/core/ui/object_detail.py +1841 -0
- nautobot/core/ui/utils.py +36 -0
- nautobot/core/urls.py +4 -9
- nautobot/core/utils/config.py +30 -3
- nautobot/core/utils/lookup.py +20 -13
- nautobot/core/views/__init__.py +6 -1
- nautobot/core/views/generic.py +47 -52
- nautobot/core/views/mixins.py +15 -25
- nautobot/core/views/paginator.py +8 -5
- nautobot/core/views/renderers.py +3 -3
- nautobot/core/views/utils.py +11 -0
- nautobot/core/wsgi.py +3 -3
- nautobot/dcim/api/serializers.py +80 -179
- nautobot/dcim/api/urls.py +5 -0
- nautobot/dcim/api/views.py +17 -4
- nautobot/dcim/apps.py +1 -0
- nautobot/dcim/choices.py +28 -0
- nautobot/dcim/factory.py +58 -0
- nautobot/dcim/filters/__init__.py +197 -24
- nautobot/dcim/forms.py +203 -12
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
- nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
- nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
- nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
- nautobot/dcim/models/__init__.py +4 -0
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +20 -22
- nautobot/dcim/models/devices.py +173 -4
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +5 -6
- nautobot/dcim/models/racks.py +6 -6
- nautobot/dcim/navigation.py +25 -224
- nautobot/dcim/signals.py +44 -0
- nautobot/dcim/tables/__init__.py +5 -3
- nautobot/dcim/tables/devices.py +96 -2
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/templates/dcim/controller/base.html +10 -0
- nautobot/dcim/templates/dcim/controller_create.html +1 -0
- nautobot/dcim/templates/dcim/controller_retrieve.html +5 -1
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +66 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +46 -0
- nautobot/dcim/templates/dcim/device/base.html +6 -42
- nautobot/dcim/templates/dcim/device/wireless.html +73 -0
- nautobot/dcim/templates/dcim/device.html +3 -1
- nautobot/dcim/templates/dcim/interface.html +1 -0
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/locationtype.html +0 -107
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +76 -0
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +34 -0
- nautobot/dcim/tests/test_api.py +172 -61
- nautobot/dcim/tests/test_filters.py +171 -109
- nautobot/dcim/tests/test_forms.py +2 -51
- nautobot/dcim/tests/test_graphql.py +0 -52
- nautobot/dcim/tests/test_models.py +126 -4
- nautobot/dcim/tests/test_signals.py +1 -0
- nautobot/dcim/tests/test_views.py +103 -11
- nautobot/dcim/urls.py +72 -27
- nautobot/dcim/utils.py +2 -2
- nautobot/dcim/views.py +369 -62
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +91 -75
- nautobot/extras/api/urls.py +4 -0
- nautobot/extras/api/views.py +78 -15
- nautobot/extras/choices.py +13 -0
- nautobot/extras/constants.py +0 -1
- nautobot/extras/context_managers.py +23 -6
- nautobot/extras/datasources/git.py +4 -1
- nautobot/extras/factory.py +27 -0
- nautobot/extras/filters/__init__.py +59 -0
- nautobot/extras/forms/forms.py +125 -30
- nautobot/extras/forms/mixins.py +3 -11
- nautobot/extras/graphql/types.py +25 -1
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/health_checks.py +2 -1
- nautobot/extras/jobs.py +62 -26
- nautobot/extras/management/__init__.py +1 -0
- nautobot/extras/management/commands/runjob.py +7 -79
- nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
- nautobot/extras/management/utils.py +87 -0
- nautobot/extras/managers.py +1 -3
- nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
- nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
- nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
- nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
- nautobot/extras/models/__init__.py +4 -0
- nautobot/extras/models/change_logging.py +7 -3
- nautobot/extras/models/customfields.py +11 -12
- nautobot/extras/models/groups.py +9 -13
- nautobot/extras/models/jobs.py +218 -37
- nautobot/extras/models/models.py +2 -2
- nautobot/extras/models/relationships.py +69 -1
- nautobot/extras/models/secrets.py +5 -0
- nautobot/extras/navigation.py +20 -262
- nautobot/extras/plugins/__init__.py +56 -32
- nautobot/extras/plugins/marketplace_manifest.yml +450 -0
- nautobot/extras/plugins/urls.py +1 -0
- nautobot/extras/plugins/views.py +48 -1
- nautobot/extras/signals.py +39 -1
- nautobot/extras/tables.py +40 -6
- nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
- nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
- nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
- nautobot/extras/templates/extras/job_detail.html +36 -6
- nautobot/extras/templates/extras/job_edit.html +5 -2
- nautobot/extras/templates/extras/job_list.html +2 -7
- nautobot/extras/templates/extras/jobqueue_retrieve.html +44 -0
- nautobot/extras/templates/extras/marketplace.html +278 -0
- nautobot/extras/templates/extras/plugins_list.html +35 -1
- nautobot/extras/templates/extras/plugins_tiles.html +79 -0
- nautobot/extras/templates/extras/role_retrieve.html +16 -0
- nautobot/extras/templates/extras/secret.html +0 -65
- nautobot/extras/templates/extras/secret_check.js +16 -0
- nautobot/extras/templates/extras/secret_create.html +114 -0
- nautobot/extras/templates/extras/secret_edit.html +1 -114
- nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
- nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
- nautobot/extras/templatetags/job_buttons.py +5 -4
- nautobot/extras/templatetags/plugins.py +69 -6
- nautobot/extras/test_jobs/api_test_job.py +1 -1
- nautobot/extras/test_jobs/atomic_transaction.py +2 -2
- nautobot/extras/test_jobs/dry_run.py +1 -1
- nautobot/extras/test_jobs/fail.py +5 -5
- nautobot/extras/test_jobs/file_output.py +1 -1
- nautobot/extras/test_jobs/file_upload_fail.py +1 -1
- nautobot/extras/test_jobs/file_upload_pass.py +1 -1
- nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
- nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
- nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
- nautobot/extras/test_jobs/log_redaction.py +1 -1
- nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
- nautobot/extras/test_jobs/modify_db.py +1 -1
- nautobot/extras/test_jobs/object_var_optional.py +1 -1
- nautobot/extras/test_jobs/object_var_required.py +1 -1
- nautobot/extras/test_jobs/object_vars.py +1 -1
- nautobot/extras/test_jobs/pass.py +3 -3
- nautobot/extras/test_jobs/profiling.py +1 -1
- nautobot/extras/test_jobs/relative_import.py +3 -3
- nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
- nautobot/extras/test_jobs/task_queues.py +1 -1
- nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
- nautobot/extras/tests/test_api.py +157 -55
- nautobot/extras/tests/test_context_managers.py +4 -1
- nautobot/extras/tests/test_customfields.py +1 -1
- nautobot/extras/tests/test_datasources.py +1 -2
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +219 -535
- nautobot/extras/tests/test_forms.py +1 -20
- nautobot/extras/tests/test_job_variables.py +73 -152
- nautobot/extras/tests/test_jobs.py +43 -54
- nautobot/extras/tests/test_models.py +71 -16
- nautobot/extras/tests/test_relationships.py +5 -2
- nautobot/extras/tests/test_utils.py +23 -2
- nautobot/extras/tests/test_views.py +183 -43
- nautobot/extras/tests/test_webhooks.py +2 -1
- nautobot/extras/urls.py +2 -20
- nautobot/extras/utils.py +118 -4
- nautobot/extras/views.py +203 -92
- nautobot/extras/webhooks.py +5 -2
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +36 -137
- nautobot/ipam/api/views.py +93 -62
- nautobot/ipam/lookups.py +62 -101
- nautobot/ipam/models.py +11 -63
- nautobot/ipam/navigation.py +0 -90
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +6 -20
- nautobot/ipam/templates/ipam/routetarget.html +0 -28
- nautobot/ipam/templates/ipam/vrf.html +0 -47
- nautobot/ipam/tests/test_api.py +8 -419
- nautobot/ipam/tests/test_filters.py +39 -119
- nautobot/ipam/tests/test_forms.py +47 -51
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +0 -41
- nautobot/ipam/tests/test_querysets.py +1 -63
- nautobot/ipam/urls.py +3 -69
- nautobot/ipam/utils/__init__.py +0 -24
- nautobot/ipam/views.py +153 -198
- nautobot/project-static/css/base.css +38 -3
- nautobot/project-static/docs/404.html +421 -19
- nautobot/project-static/docs/apps/index.html +421 -19
- nautobot/project-static/docs/apps/nautobot-apps.html +421 -19
- nautobot/project-static/docs/assets/extra.css +5 -1
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +421 -172
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +425 -21
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +424 -22
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9809 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +424 -63
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +457 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +425 -25
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +457 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +425 -215
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +430 -342
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5799 -1054
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +447 -176
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +460 -21
- nautobot/project-static/docs/development/apps/api/configuration-view.html +421 -19
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/global-search.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/graphql.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/index.html +421 -19
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +424 -41
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +421 -19
- nautobot/project-static/docs/development/apps/api/prometheus.html +421 -19
- nautobot/project-static/docs/development/apps/api/setup.html +425 -155
- nautobot/project-static/docs/development/apps/api/testing.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +701 -130
- nautobot/project-static/docs/development/apps/api/views/base-template.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/index.html +423 -20
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +425 -19
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +451 -19
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/notes.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/urls.html +421 -19
- nautobot/project-static/docs/development/apps/index.html +421 -19
- nautobot/project-static/docs/development/apps/migration/code-updates.html +422 -52
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +422 -20
- nautobot/project-static/docs/development/apps/migration/from-v1.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +424 -22
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9219 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9333 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9474 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9517 -0
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +424 -22
- nautobot/project-static/docs/development/core/application-registry.html +421 -19
- nautobot/project-static/docs/development/core/best-practices.html +421 -19
- nautobot/project-static/docs/development/core/bootstrap-ui.html +421 -19
- nautobot/project-static/docs/development/core/caching.html +421 -19
- nautobot/project-static/docs/development/core/controllers.html +423 -19
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +490 -45
- nautobot/project-static/docs/development/core/generic-views.html +421 -19
- nautobot/project-static/docs/development/core/getting-started.html +566 -179
- nautobot/project-static/docs/development/core/homepage.html +432 -30
- nautobot/project-static/docs/development/core/index.html +421 -19
- nautobot/project-static/docs/development/core/local-k8s.html +9453 -0
- nautobot/project-static/docs/development/core/model-checklist.html +424 -22
- nautobot/project-static/docs/development/core/model-features.html +421 -19
- nautobot/project-static/docs/development/core/natural-keys.html +421 -19
- nautobot/project-static/docs/development/core/navigation-menu.html +438 -26
- nautobot/project-static/docs/development/core/release-checklist.html +435 -45
- nautobot/project-static/docs/development/core/role-internals.html +421 -19
- nautobot/project-static/docs/development/core/settings.html +421 -19
- nautobot/project-static/docs/development/core/style-guide.html +421 -19
- nautobot/project-static/docs/development/core/templates.html +431 -22
- nautobot/project-static/docs/development/core/testing.html +421 -19
- nautobot/project-static/docs/development/core/ui-component-framework.html +11020 -0
- nautobot/project-static/docs/development/core/user-preferences.html +424 -22
- nautobot/project-static/docs/development/index.html +421 -19
- nautobot/project-static/docs/development/jobs/index.html +546 -160
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +421 -19
- nautobot/project-static/docs/index.html +421 -19
- nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
- nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
- nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
- nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
- nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
- nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
- nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
- nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +426 -20
- nautobot/project-static/docs/overview/design_philosophy.html +421 -19
- nautobot/project-static/docs/release-notes/index.html +445 -22
- nautobot/project-static/docs/release-notes/version-1.0.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.1.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.2.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.3.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.4.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.5.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.6.html +634 -667
- nautobot/project-static/docs/release-notes/version-2.0.html +421 -19
- nautobot/project-static/docs/release-notes/version-2.1.html +421 -19
- nautobot/project-static/docs/release-notes/version-2.2.html +421 -19
- nautobot/project-static/docs/release-notes/version-2.3.html +684 -886
- nautobot/project-static/docs/release-notes/version-2.4.html +10007 -0
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +334 -270
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +421 -19
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +421 -19
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +423 -21
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +433 -32
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +421 -19
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +765 -180
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +434 -29
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/index.html +426 -20
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/services.html +421 -19
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +421 -19
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +442 -41
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +435 -66
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +435 -66
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +427 -21
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +457 -20
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +447 -22
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9333 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +424 -22
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +424 -22
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9271 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9175 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9169 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9235 -0
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +421 -19
- nautobot/project-static/docs/user-guide/index.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +9575 -0
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +426 -20
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9182 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9250 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +489 -56
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +421 -19
- nautobot/project-static/img/jinja_logo.svg +97 -0
- nautobot/project-static/js/forms.js +5 -0
- nautobot/project-static/js/nav_menu.js +2 -1
- nautobot/tenancy/api/serializers.py +0 -2
- nautobot/tenancy/factory.py +1 -1
- nautobot/tenancy/navigation.py +0 -29
- nautobot/tenancy/templates/tenancy/tenant.html +4 -91
- nautobot/tenancy/tests/test_filters.py +29 -134
- nautobot/tenancy/views.py +32 -23
- nautobot/users/admin.py +3 -1
- nautobot/users/api/serializers.py +4 -5
- nautobot/users/api/views.py +1 -1
- nautobot/users/forms.py +19 -0
- nautobot/users/templates/users/preferences.html +22 -0
- nautobot/users/tests/test_filters.py +1 -19
- nautobot/users/tests/test_views.py +57 -0
- nautobot/users/utils.py +8 -0
- nautobot/users/views.py +48 -11
- nautobot/virtualization/api/serializers.py +4 -4
- nautobot/virtualization/filters.py +2 -20
- nautobot/virtualization/navigation.py +0 -48
- nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
- nautobot/virtualization/tests/test_filters.py +57 -183
- nautobot/virtualization/views.py +18 -15
- nautobot/wireless/__init__.py +0 -0
- nautobot/wireless/api/__init__.py +0 -0
- nautobot/wireless/api/serializers.py +44 -0
- nautobot/wireless/api/urls.py +20 -0
- nautobot/wireless/api/views.py +34 -0
- nautobot/wireless/apps.py +8 -0
- nautobot/wireless/choices.py +345 -0
- nautobot/wireless/factory.py +138 -0
- nautobot/wireless/filters.py +167 -0
- nautobot/wireless/forms.py +283 -0
- nautobot/wireless/homepage.py +19 -0
- nautobot/wireless/migrations/0001_initial.py +223 -0
- nautobot/wireless/migrations/__init__.py +0 -0
- nautobot/wireless/models.py +207 -0
- nautobot/wireless/navigation.py +105 -0
- nautobot/wireless/tables.py +244 -0
- nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
- nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
- nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +64 -0
- nautobot/wireless/tests/__init__.py +0 -0
- nautobot/wireless/tests/test_api.py +247 -0
- nautobot/wireless/tests/test_filters.py +54 -0
- nautobot/wireless/tests/test_models.py +22 -0
- nautobot/wireless/tests/test_views.py +378 -0
- nautobot/wireless/urls.py +13 -0
- nautobot/wireless/views.py +129 -0
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +11 -14
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +674 -551
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
- nautobot/core/utils/navigation.py +0 -54
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from django.test.utils import TestContextDecorator
|
|
2
|
+
|
|
3
|
+
from nautobot.core.events import _EVENT_BROKERS, deregister_event_broker, load_event_brokers
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class load_event_broker_override_settings(TestContextDecorator):
|
|
7
|
+
def __init__(self, **kwargs) -> None:
|
|
8
|
+
self.options = kwargs
|
|
9
|
+
super().__init__()
|
|
10
|
+
|
|
11
|
+
def enable(self):
|
|
12
|
+
"""Registered event brokers"""
|
|
13
|
+
load_event_brokers(self.options["EVENT_BROKERS"])
|
|
14
|
+
|
|
15
|
+
def disable(self):
|
|
16
|
+
"""Clear all registered event brokers"""
|
|
17
|
+
for event_broker in _EVENT_BROKERS:
|
|
18
|
+
deregister_event_broker(event_broker)
|
nautobot/core/testing/filters.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
from __future__ import annotations # python 3.8
|
|
2
|
-
|
|
3
1
|
import random
|
|
4
2
|
import string
|
|
3
|
+
from typing import ClassVar, Iterable
|
|
5
4
|
|
|
6
5
|
from django.contrib.contenttypes.models import ContentType
|
|
7
6
|
from django.db.models import Count, Q, QuerySet
|
|
@@ -21,6 +20,7 @@ from nautobot.core.filters import (
|
|
|
21
20
|
)
|
|
22
21
|
from nautobot.core.models.generics import PrimaryModel
|
|
23
22
|
from nautobot.core.testing import views
|
|
23
|
+
from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
|
|
24
24
|
from nautobot.extras.models import Contact, ContactAssociation, Role, Status, Tag, Team
|
|
25
25
|
from nautobot.tenancy import models
|
|
26
26
|
|
|
@@ -30,8 +30,6 @@ class FilterTestCases:
|
|
|
30
30
|
class BaseFilterTestCase(views.TestCase):
|
|
31
31
|
"""Base class for testing of FilterSets."""
|
|
32
32
|
|
|
33
|
-
queryset: QuerySet
|
|
34
|
-
|
|
35
33
|
def get_filterset_test_values(self, field_name, queryset=None):
|
|
36
34
|
"""Returns a list of distinct values from the requested queryset field to use in filterset tests.
|
|
37
35
|
|
|
@@ -73,7 +71,8 @@ class FilterTestCases:
|
|
|
73
71
|
class FilterTestCase(BaseFilterTestCase):
|
|
74
72
|
"""Add common tests for all FilterSets."""
|
|
75
73
|
|
|
76
|
-
|
|
74
|
+
queryset: ClassVar[QuerySet]
|
|
75
|
+
filterset: ClassVar[FilterSet]
|
|
77
76
|
|
|
78
77
|
# filter predicate fields that should be excluded from q test case
|
|
79
78
|
exclude_q_filter_predicates = []
|
|
@@ -85,34 +84,18 @@ class FilterTestCases:
|
|
|
85
84
|
# ["filter1"],
|
|
86
85
|
# ["filter2", "field2__name"],
|
|
87
86
|
# ]
|
|
88
|
-
generic_filter_tests
|
|
87
|
+
generic_filter_tests: ClassVar[Iterable]
|
|
88
|
+
|
|
89
|
+
def setUp(self):
|
|
90
|
+
for attr in ["queryset", "filterset", "generic_filter_tests"]:
|
|
91
|
+
if not hasattr(self, attr):
|
|
92
|
+
raise NotImplementedError(f'{self} is missing a value for required attribute "{attr}"')
|
|
93
|
+
super().setUp()
|
|
89
94
|
|
|
90
95
|
def get_q_filter(self):
|
|
91
96
|
"""Helper method to return q filter."""
|
|
92
97
|
return self.filterset.declared_filters["q"].filter_predicates
|
|
93
98
|
|
|
94
|
-
def test_id(self):
|
|
95
|
-
"""Verify that the filterset supports filtering by id with only lookup `__n`."""
|
|
96
|
-
with self.subTest("Assert `id`"):
|
|
97
|
-
params = {"id": list(self.queryset.values_list("pk", flat=True)[:2])}
|
|
98
|
-
expected_queryset = self.queryset.filter(id__in=params["id"])
|
|
99
|
-
filterset = self.filterset(params, self.queryset)
|
|
100
|
-
self.assertTrue(filterset.is_valid())
|
|
101
|
-
self.assertQuerysetEqualAndNotEmpty(filterset.qs.order_by("id"), expected_queryset.order_by("id"))
|
|
102
|
-
|
|
103
|
-
with self.subTest("Assert negate lookup"):
|
|
104
|
-
params = {"id__n": list(self.queryset.values_list("pk", flat=True)[:2])}
|
|
105
|
-
expected_queryset = self.queryset.exclude(id__in=params["id__n"])
|
|
106
|
-
filterset = self.filterset(params, self.queryset)
|
|
107
|
-
self.assertTrue(filterset.is_valid())
|
|
108
|
-
self.assertQuerysetEqualAndNotEmpty(filterset.qs.order_by("id"), expected_queryset.order_by("id"))
|
|
109
|
-
|
|
110
|
-
with self.subTest("Assert invalid lookup"):
|
|
111
|
-
params = {"id__in": list(self.queryset.values_list("pk", flat=True)[:2])}
|
|
112
|
-
filterset = self.filterset(params, self.queryset)
|
|
113
|
-
self.assertFalse(filterset.is_valid())
|
|
114
|
-
self.assertIn("Unknown filter field", filterset.errors.as_text())
|
|
115
|
-
|
|
116
99
|
def test_invalid_filter(self):
|
|
117
100
|
"""Verify that the filterset reports as invalid when initialized with an unsupported filter parameter."""
|
|
118
101
|
params = {"ice_cream_flavor": ["chocolate"]}
|
|
@@ -141,15 +124,22 @@ class FilterTestCases:
|
|
|
141
124
|
)
|
|
142
125
|
This expects a field named `devices` on the model and a filter named `devices` on the filterset.
|
|
143
126
|
"""
|
|
127
|
+
if not any(test[0] == "id" for test in self.generic_filter_tests):
|
|
128
|
+
self.generic_filter_tests = (["id"], *self.generic_filter_tests)
|
|
129
|
+
|
|
144
130
|
if getattr(self.queryset.model, "is_contact_associable_model", False):
|
|
145
|
-
for
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
131
|
+
if not any(test[0] == "contacts" for test in self.generic_filter_tests):
|
|
132
|
+
self.generic_filter_tests = (
|
|
133
|
+
*self.generic_filter_tests,
|
|
134
|
+
["contacts", "associated_contacts__contact__name"],
|
|
135
|
+
["contacts", "associated_contacts__contact__id"],
|
|
136
|
+
)
|
|
137
|
+
if not any(test[0] == "teams" for test in self.generic_filter_tests):
|
|
138
|
+
self.generic_filter_tests = (
|
|
139
|
+
*self.generic_filter_tests,
|
|
140
|
+
["teams", "associated_contacts__team__name"],
|
|
141
|
+
["teams", "associated_contacts__team__id"],
|
|
142
|
+
)
|
|
153
143
|
|
|
154
144
|
# Make sure we have at least 3 contacts and 3 teams in the database
|
|
155
145
|
if Contact.objects.count() < 3:
|
|
@@ -177,9 +167,6 @@ class FilterTestCases:
|
|
|
177
167
|
status=Status.objects.get_for_model(ContactAssociation).last(),
|
|
178
168
|
)
|
|
179
169
|
|
|
180
|
-
if not self.generic_filter_tests:
|
|
181
|
-
self.skipTest("No generic_filter_tests defined?")
|
|
182
|
-
|
|
183
170
|
for test in self.generic_filter_tests:
|
|
184
171
|
filter_name = test[0]
|
|
185
172
|
field_name = test[-1] # default to filter_name if a second list item was not supplied
|
|
@@ -238,10 +225,6 @@ class FilterTestCases:
|
|
|
238
225
|
qs_result = self.queryset.filter(tags=tags[0]).filter(tags=tags[1]).distinct()
|
|
239
226
|
self.assertQuerysetEqualAndNotEmpty(filterset_result, qs_result)
|
|
240
227
|
|
|
241
|
-
def test_q_filter_exists(self):
|
|
242
|
-
"""Test the `q` filter exists on a filterset, does not validate the filter works as expected."""
|
|
243
|
-
self.assertIn("q", self.filterset.declared_filters)
|
|
244
|
-
|
|
245
228
|
def _assert_valid_filter_predicates(self, obj, field_name):
|
|
246
229
|
self.assertTrue(
|
|
247
230
|
hasattr(obj, field_name),
|
|
@@ -377,27 +360,27 @@ class FilterTestCases:
|
|
|
377
360
|
filter_field, (ContentTypeFilter, ContentTypeMultipleChoiceFilter, ContentTypeChoiceFilter)
|
|
378
361
|
)
|
|
379
362
|
|
|
363
|
+
# Test cases should just explicitly include `name` as a generic_filter_tests entry
|
|
364
|
+
@class_deprecated_in_favor_of(FilterTestCase) # pylint: disable=undefined-variable
|
|
380
365
|
class NameOnlyFilterTestCase(FilterTestCase):
|
|
381
366
|
"""Add simple tests for filtering by name."""
|
|
382
367
|
|
|
383
|
-
def
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
self.assertTrue(filterset.is_valid())
|
|
388
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
389
|
-
filterset.qs.order_by("name"), self.queryset.filter(name__in=params["name"]).order_by("name")
|
|
390
|
-
)
|
|
368
|
+
def test_filters_generic(self):
|
|
369
|
+
if not any(test[0] == "name" for test in self.generic_filter_tests):
|
|
370
|
+
self.generic_filter_tests = (["name"], *self.generic_filter_tests)
|
|
371
|
+
super().test_filters_generic()
|
|
391
372
|
|
|
392
|
-
|
|
373
|
+
# Test cases should just explicitly include `name` and `slug` as generic_filter_tests entries
|
|
374
|
+
@class_deprecated_in_favor_of(FilterTestCase) # pylint: disable=undefined-variable
|
|
375
|
+
class NameSlugFilterTestCase(FilterTestCase):
|
|
393
376
|
"""Add simple tests for filtering by name and by slug."""
|
|
394
377
|
|
|
395
|
-
def
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
378
|
+
def test_filters_generic(self):
|
|
379
|
+
if not any(test[0] == "slug" for test in self.generic_filter_tests):
|
|
380
|
+
self.generic_filter_tests = (["slug"], *self.generic_filter_tests)
|
|
381
|
+
if not any(test[0] == "name" for test in self.generic_filter_tests):
|
|
382
|
+
self.generic_filter_tests = (["name"], *self.generic_filter_tests)
|
|
383
|
+
super().test_filters_generic()
|
|
401
384
|
|
|
402
385
|
class TenancyFilterTestCaseMixin(views.TestCase):
|
|
403
386
|
"""Add test cases for tenant and tenant-group filters."""
|
nautobot/core/testing/mixins.py
CHANGED
|
@@ -144,18 +144,13 @@ class NautobotTestCaseMixin:
|
|
|
144
144
|
# Permissions management
|
|
145
145
|
#
|
|
146
146
|
|
|
147
|
-
def add_permissions(self, *names
|
|
147
|
+
def add_permissions(self, *names):
|
|
148
148
|
"""
|
|
149
149
|
Assign a set of permissions to the test user. Accepts permission names in the form <app>.<action>_<model>.
|
|
150
|
-
Additional keyword arguments will be passed to the ObjectPermission constructor to allow creating more detailed permissions.
|
|
151
|
-
|
|
152
|
-
Examples:
|
|
153
|
-
>>> add_permissions("ipam.add_vlangroup", "ipam.view_vlangroup")
|
|
154
|
-
>>> add_permissions("ipam.add_vlangroup", "ipam.view_vlangroup", constraints={"pk": "uuid-1234"})
|
|
155
150
|
"""
|
|
156
151
|
for name in names:
|
|
157
152
|
ct, action = permissions.resolve_permission_ct(name)
|
|
158
|
-
obj_perm = users_models.ObjectPermission(name=name, actions=[action]
|
|
153
|
+
obj_perm = users_models.ObjectPermission(name=name, actions=[action])
|
|
159
154
|
obj_perm.save()
|
|
160
155
|
obj_perm.users.add(self.user)
|
|
161
156
|
obj_perm.object_types.add(ct)
|
nautobot/core/testing/views.py
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from __future__ import annotations # python 3.8
|
|
2
|
-
|
|
3
1
|
import contextlib
|
|
4
2
|
import re
|
|
5
3
|
from typing import Optional, Sequence
|
|
@@ -23,7 +21,6 @@ from nautobot.core.models.tree_queries import TreeModel
|
|
|
23
21
|
from nautobot.core.templatetags import helpers
|
|
24
22
|
from nautobot.core.testing import mixins, utils
|
|
25
23
|
from nautobot.core.utils import lookup
|
|
26
|
-
from nautobot.dcim.models.device_components import ComponentModel
|
|
27
24
|
from nautobot.extras import choices as extras_choices, models as extras_models, querysets as extras_querysets
|
|
28
25
|
from nautobot.extras.forms import CustomFieldModelFormMixin, RelationshipModelFormMixin
|
|
29
26
|
from nautobot.extras.models import CustomFieldModel, RelationshipModel
|
|
@@ -174,10 +171,7 @@ class ViewTestCases:
|
|
|
174
171
|
instance = self._get_queryset().first()
|
|
175
172
|
|
|
176
173
|
# Add model-level permission
|
|
177
|
-
|
|
178
|
-
obj_perm.save()
|
|
179
|
-
obj_perm.users.add(self.user)
|
|
180
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
174
|
+
self.add_permissions(f"{self.model._meta.app_label}.view_{self.model._meta.model_name}")
|
|
181
175
|
|
|
182
176
|
# Try GET with model-level permission
|
|
183
177
|
response = self.client.get(instance.get_absolute_url())
|
|
@@ -326,10 +320,7 @@ class ViewTestCases:
|
|
|
326
320
|
initial_count = self._get_queryset().count()
|
|
327
321
|
|
|
328
322
|
# Assign unconstrained permission
|
|
329
|
-
|
|
330
|
-
obj_perm.save()
|
|
331
|
-
obj_perm.users.add(self.user)
|
|
332
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
323
|
+
self.add_permissions(f"{self.model._meta.app_label}.add_{self.model._meta.model_name}")
|
|
333
324
|
|
|
334
325
|
# Try GET with model-level permission
|
|
335
326
|
self.assertHttpStatus(self.client.get(self._get_url("add")), 200)
|
|
@@ -436,32 +427,6 @@ class ViewTestCases:
|
|
|
436
427
|
if isinstance(model_class, PrimaryModel):
|
|
437
428
|
self.assertIsNotNone(fields.get("tags"))
|
|
438
429
|
|
|
439
|
-
def test_slug_autocreation(self):
|
|
440
|
-
"""Test that slug is autocreated through ORM."""
|
|
441
|
-
# This really should go on a models test page, but we don't have test structures for models.
|
|
442
|
-
if getattr(self.model, "slug_source", None) is not None:
|
|
443
|
-
obj = self.model.objects.get(**{self.slug_source: self.slug_test_object})
|
|
444
|
-
expected_slug = self.slugify_function(getattr(obj, self.slug_source))
|
|
445
|
-
self.assertEqual(obj.slug, expected_slug)
|
|
446
|
-
|
|
447
|
-
def test_slug_not_modified(self):
|
|
448
|
-
"""Ensure save method does not modify slug that is passed in."""
|
|
449
|
-
# This really should go on a models test page, but we don't have test structures for models.
|
|
450
|
-
if getattr(self.model, "slug_source", None) is not None:
|
|
451
|
-
new_slug_source_value = "kwyjibo"
|
|
452
|
-
|
|
453
|
-
obj = self.model.objects.get(**{self.slug_source: self.slug_test_object})
|
|
454
|
-
expected_slug = self.slugify_function(getattr(obj, self.slug_source))
|
|
455
|
-
# Update slug source field str
|
|
456
|
-
filter_ = self.slug_source + "__exact"
|
|
457
|
-
self.model.objects.filter(**{filter_: self.slug_test_object}).update(
|
|
458
|
-
**{self.slug_source: new_slug_source_value}
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
obj.refresh_from_db()
|
|
462
|
-
self.assertEqual(getattr(obj, self.slug_source), new_slug_source_value)
|
|
463
|
-
self.assertEqual(obj.slug, expected_slug)
|
|
464
|
-
|
|
465
430
|
class EditObjectViewTestCase(ModelViewTestCase):
|
|
466
431
|
"""
|
|
467
432
|
Edit a single existing instance.
|
|
@@ -494,10 +459,7 @@ class ViewTestCases:
|
|
|
494
459
|
instance = self._get_queryset().first()
|
|
495
460
|
|
|
496
461
|
# Assign model-level permission
|
|
497
|
-
|
|
498
|
-
obj_perm.save()
|
|
499
|
-
obj_perm.users.add(self.user)
|
|
500
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
462
|
+
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
501
463
|
|
|
502
464
|
# Try GET with model-level permission
|
|
503
465
|
self.assertHttpStatus(self.client.get(self._get_url("edit", instance)), 200)
|
|
@@ -618,10 +580,7 @@ class ViewTestCases:
|
|
|
618
580
|
instance_note_pk_list.append(note.pk)
|
|
619
581
|
|
|
620
582
|
# Assign model-level permission
|
|
621
|
-
|
|
622
|
-
obj_perm.save()
|
|
623
|
-
obj_perm.users.add(self.user)
|
|
624
|
-
obj_perm.object_types.add(assigned_object_type)
|
|
583
|
+
self.add_permissions(f"{self.model._meta.app_label}.delete_{self.model._meta.model_name}")
|
|
625
584
|
|
|
626
585
|
# Try GET with model-level permission
|
|
627
586
|
self.assertHttpStatus(self.client.get(self._get_url("delete", instance)), 200)
|
|
@@ -657,10 +616,7 @@ class ViewTestCases:
|
|
|
657
616
|
instance = self.get_deletable_object()
|
|
658
617
|
|
|
659
618
|
# Assign model-level permission
|
|
660
|
-
|
|
661
|
-
obj_perm.save()
|
|
662
|
-
obj_perm.users.add(self.user)
|
|
663
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
619
|
+
self.add_permissions(f"{self.model._meta.app_label}.delete_{self.model._meta.model_name}")
|
|
664
620
|
|
|
665
621
|
# Try GET with model-level permission
|
|
666
622
|
self.assertHttpStatus(self.client.get(self._get_url("delete", instance)), 200)
|
|
@@ -865,10 +821,7 @@ class ViewTestCases:
|
|
|
865
821
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
|
|
866
822
|
def test_list_objects_with_permission(self):
|
|
867
823
|
# Add model-level permission
|
|
868
|
-
|
|
869
|
-
obj_perm.save()
|
|
870
|
-
obj_perm.users.add(self.user)
|
|
871
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
824
|
+
self.add_permissions(f"{self.model._meta.app_label}.view_{self.model._meta.model_name}")
|
|
872
825
|
|
|
873
826
|
# Try GET with model-level permission
|
|
874
827
|
response = self.client.get(self._get_url("list"))
|
|
@@ -881,11 +834,17 @@ class ViewTestCases:
|
|
|
881
834
|
# Check if breadcrumb is rendered correctly
|
|
882
835
|
self.assertBodyContains(response, f'<a href="{list_url}">{title}</a>', html=True)
|
|
883
836
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
837
|
+
with self.subTest("Assert import-objects URL is absent due to user permissions"):
|
|
838
|
+
self.assertNotIn(
|
|
839
|
+
reverse("extras:job_run_by_class_path", kwargs={"class_path": "nautobot.core.jobs.ImportObjects"}),
|
|
840
|
+
response_body,
|
|
841
|
+
)
|
|
842
|
+
|
|
843
|
+
if "example_app" in settings.PLUGINS:
|
|
844
|
+
with self.subTest("Assert example-app banner is present"):
|
|
845
|
+
self.assertIn(
|
|
846
|
+
f"<div>You are viewing a table of {self.model._meta.verbose_name_plural}</div>", response_body
|
|
847
|
+
)
|
|
889
848
|
|
|
890
849
|
return response
|
|
891
850
|
|
|
@@ -992,13 +951,7 @@ class ViewTestCases:
|
|
|
992
951
|
}
|
|
993
952
|
|
|
994
953
|
# Assign non-constrained permission
|
|
995
|
-
|
|
996
|
-
name="Test permission",
|
|
997
|
-
actions=["add"],
|
|
998
|
-
)
|
|
999
|
-
obj_perm.save()
|
|
1000
|
-
obj_perm.users.add(self.user)
|
|
1001
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
954
|
+
self.add_permissions(f"{self.model._meta.app_label}.add_{self.model._meta.model_name}")
|
|
1002
955
|
|
|
1003
956
|
# Bulk create objects
|
|
1004
957
|
response = self.client.post(**request)
|
|
@@ -1052,34 +1005,6 @@ class ViewTestCases:
|
|
|
1052
1005
|
pass
|
|
1053
1006
|
self.assertEqual(matching_count, self.bulk_create_count)
|
|
1054
1007
|
|
|
1055
|
-
class BulkImportObjectsViewTestCase(ModelViewTestCase): # 3.0 TODO: remove this test mixin, no longer relevant.
|
|
1056
|
-
"""
|
|
1057
|
-
Vestigial test case, to be removed in 3.0.
|
|
1058
|
-
|
|
1059
|
-
This is vestigial since the introduction of the ImportObjects system Job to handle bulk-import of all
|
|
1060
|
-
content-types via REST API serializers. The parsing of CSV data by the serializer is exercised by
|
|
1061
|
-
APIViewTestCases.CreateObjectViewTestCase.test_recreate_object_csv(), and the basic operation of the Job is
|
|
1062
|
-
exercised by nautobot.core.tests.test_jobs.
|
|
1063
|
-
"""
|
|
1064
|
-
|
|
1065
|
-
csv_data = ()
|
|
1066
|
-
|
|
1067
|
-
def _get_csv_data(self):
|
|
1068
|
-
return "\n".join(self.csv_data)
|
|
1069
|
-
|
|
1070
|
-
# Just in case Apps are extending any of these tests and calling super() in them.
|
|
1071
|
-
def test_bulk_import_objects_without_permission(self):
|
|
1072
|
-
pass
|
|
1073
|
-
|
|
1074
|
-
def test_bulk_import_objects_with_permission(self):
|
|
1075
|
-
pass
|
|
1076
|
-
|
|
1077
|
-
def test_bulk_import_objects_with_permission_csv_file(self):
|
|
1078
|
-
pass
|
|
1079
|
-
|
|
1080
|
-
def test_bulk_import_objects_with_constrained_permission(self):
|
|
1081
|
-
pass
|
|
1082
|
-
|
|
1083
1008
|
class BulkEditObjectsViewTestCase(ModelViewTestCase):
|
|
1084
1009
|
"""
|
|
1085
1010
|
Edit multiple instances.
|
|
@@ -1117,10 +1042,7 @@ class ViewTestCases:
|
|
|
1117
1042
|
data.update(utils.post_data(self.bulk_edit_data))
|
|
1118
1043
|
|
|
1119
1044
|
# Assign model-level permission
|
|
1120
|
-
|
|
1121
|
-
obj_perm.save()
|
|
1122
|
-
obj_perm.users.add(self.user)
|
|
1123
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1045
|
+
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
1124
1046
|
|
|
1125
1047
|
# Try POST with model-level permission
|
|
1126
1048
|
self.assertHttpStatus(self.client.post(self._get_url("bulk_edit"), data), 302)
|
|
@@ -1135,10 +1057,7 @@ class ViewTestCases:
|
|
|
1135
1057
|
"_all": "on",
|
|
1136
1058
|
}
|
|
1137
1059
|
# Assign model-level permission
|
|
1138
|
-
|
|
1139
|
-
obj_perm.save()
|
|
1140
|
-
obj_perm.users.add(self.user)
|
|
1141
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1060
|
+
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
1142
1061
|
|
|
1143
1062
|
# Try POST with model-level permission
|
|
1144
1063
|
response = self.client.post(self._get_url("bulk_edit"), selected_data)
|
|
@@ -1282,10 +1201,7 @@ class ViewTestCases:
|
|
|
1282
1201
|
}
|
|
1283
1202
|
|
|
1284
1203
|
# Assign unconstrained permission
|
|
1285
|
-
|
|
1286
|
-
obj_perm.save()
|
|
1287
|
-
obj_perm.users.add(self.user)
|
|
1288
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1204
|
+
self.add_permissions(f"{self.model._meta.app_label}.delete_{self.model._meta.model_name}")
|
|
1289
1205
|
|
|
1290
1206
|
# Try POST with model-level permission
|
|
1291
1207
|
self.assertHttpStatus(self.client.post(self._get_url("bulk_delete"), data), 302)
|
|
@@ -1301,10 +1217,7 @@ class ViewTestCases:
|
|
|
1301
1217
|
}
|
|
1302
1218
|
|
|
1303
1219
|
# Assign unconstrained permission
|
|
1304
|
-
|
|
1305
|
-
obj_perm.save()
|
|
1306
|
-
obj_perm.users.add(self.user)
|
|
1307
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1220
|
+
self.add_permissions(f"{self.model._meta.app_label}.delete_{self.model._meta.model_name}")
|
|
1308
1221
|
|
|
1309
1222
|
# Try POST with the selected data first. Emulating selecting all -> pressing Delete Selected button.
|
|
1310
1223
|
response = self.client.post(self._get_url("bulk_delete"), selected_data)
|
|
@@ -1418,10 +1331,7 @@ class ViewTestCases:
|
|
|
1418
1331
|
data.update(self.rename_data)
|
|
1419
1332
|
|
|
1420
1333
|
# Assign model-level permission
|
|
1421
|
-
|
|
1422
|
-
obj_perm.save()
|
|
1423
|
-
obj_perm.users.add(self.user)
|
|
1424
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1334
|
+
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
1425
1335
|
|
|
1426
1336
|
# Try POST with model-level permission
|
|
1427
1337
|
self.assertHttpStatus(self.client.post(self._get_url("bulk_rename"), data), 302)
|
|
@@ -1531,16 +1441,11 @@ class ViewTestCases:
|
|
|
1531
1441
|
maxDiff = None
|
|
1532
1442
|
bulk_add_data = None
|
|
1533
1443
|
"""Used for bulk-add (distinct from bulk-create) view testing; self.bulk_create_data will be used if unset."""
|
|
1534
|
-
selected_objects: list[ComponentModel]
|
|
1535
|
-
selected_objects_parent_name: str
|
|
1536
1444
|
|
|
1537
1445
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
1538
1446
|
def test_bulk_add_component(self):
|
|
1539
1447
|
"""Test bulk-adding this component to devices/virtual-machines."""
|
|
1540
|
-
|
|
1541
|
-
obj_perm.save()
|
|
1542
|
-
obj_perm.users.add(self.user)
|
|
1543
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1448
|
+
self.add_permissions(f"{self.model._meta.app_label}.add_{self.model._meta.model_name}")
|
|
1544
1449
|
|
|
1545
1450
|
initial_count = self._get_queryset().count()
|
|
1546
1451
|
|
|
@@ -1584,10 +1489,7 @@ class ViewTestCases:
|
|
|
1584
1489
|
|
|
1585
1490
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
1586
1491
|
def test_bulk_rename(self):
|
|
1587
|
-
|
|
1588
|
-
obj_perm.save()
|
|
1589
|
-
obj_perm.users.add(self.user)
|
|
1590
|
-
obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
|
|
1492
|
+
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
1591
1493
|
|
|
1592
1494
|
objects = self.selected_objects
|
|
1593
1495
|
pk_list = [obj.pk for obj in objects]
|
|
@@ -9,6 +9,7 @@ from example_app.models import ExampleModel
|
|
|
9
9
|
class AppHomeTestCase(SeleniumTestCase):
|
|
10
10
|
"""Integration test the Example App homepage extensions."""
|
|
11
11
|
|
|
12
|
+
fixtures = ["user-data.json"] # bob/bob
|
|
12
13
|
layout = {
|
|
13
14
|
"Organization": {
|
|
14
15
|
"Locations": {"model": Location, "permission": "dcim.view_location"},
|
|
@@ -11,6 +11,8 @@ from nautobot.extras.models import CustomField, CustomFieldChoice, Status
|
|
|
11
11
|
class ListViewFilterTestCase(SeleniumTestCase):
|
|
12
12
|
"""Integration test for the list view filter ui."""
|
|
13
13
|
|
|
14
|
+
fixtures = ["user-data.json"]
|
|
15
|
+
|
|
14
16
|
def setUp(self):
|
|
15
17
|
super().setUp()
|
|
16
18
|
self.login(self.user.username, self.password)
|
|
@@ -7,6 +7,7 @@ from nautobot.tenancy.models import Tenant
|
|
|
7
7
|
class HomeTestCase(SeleniumTestCase):
|
|
8
8
|
"""Integration tests against the home page."""
|
|
9
9
|
|
|
10
|
+
fixtures = ["user-data.json"] # bob/bob
|
|
10
11
|
layout = {
|
|
11
12
|
"Organization": {
|
|
12
13
|
"Locations": {"model": Location, "permission": "dcim.view_location"},
|
|
@@ -14,7 +14,7 @@ class AuthenticationEnforcedTestCase(TestCase):
|
|
|
14
14
|
|
|
15
15
|
def test_all_views_require_authentication(self):
|
|
16
16
|
self.client.logout()
|
|
17
|
-
url_patterns = get_url_patterns()
|
|
17
|
+
url_patterns = get_url_patterns(ignore_redirects=True)
|
|
18
18
|
|
|
19
19
|
for url_pattern in url_patterns:
|
|
20
20
|
with self.subTest(url_pattern=url_pattern):
|
|
@@ -31,7 +31,6 @@ class AuthenticationEnforcedTestCase(TestCase):
|
|
|
31
31
|
"/health/",
|
|
32
32
|
"/login/",
|
|
33
33
|
"/media-failure/",
|
|
34
|
-
"/robots.txt",
|
|
35
34
|
"/template.css",
|
|
36
35
|
]:
|
|
37
36
|
self.assertHttpStatus(response, 200, msg=url)
|