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,36 @@
|
|
|
1
|
+
from django.template import Context
|
|
2
|
+
from django.template.loader import get_template
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def flatten_context(context) -> dict:
|
|
6
|
+
"""
|
|
7
|
+
If the given context is already a dict, return it unmodified; if it is a Context, flatten it to a dict.
|
|
8
|
+
|
|
9
|
+
This is working around a bug (not sure if in Django or in our code) where, if a `Context`'s `dicts` contain
|
|
10
|
+
a `RequestContext`, calling `Context.flatten()` throws an exception.
|
|
11
|
+
"""
|
|
12
|
+
if isinstance(context, dict):
|
|
13
|
+
return context
|
|
14
|
+
flat = {}
|
|
15
|
+
for d in context.dicts:
|
|
16
|
+
if isinstance(d, dict):
|
|
17
|
+
flat.update(d)
|
|
18
|
+
else:
|
|
19
|
+
flat.update(flatten_context(d))
|
|
20
|
+
return flat
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def render_component_template(template_path: str, context: Context, **kwargs) -> str:
|
|
24
|
+
"""
|
|
25
|
+
Render the template located at the given path with the given context, possibly augmented via additional kwargs.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
template_path (str): Path to the template to render, for example `"components/tab/label_wrapper.html"`.
|
|
29
|
+
context (Context): Rendering context for the template
|
|
30
|
+
**kwargs (dict): Additional key/value pairs to extend the context with for this specific template.
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
>>> render_component_template(self.label_wrapper_template_path, context, tab_id=self.tab_id, label="Hello")
|
|
34
|
+
"""
|
|
35
|
+
with context.update(kwargs):
|
|
36
|
+
return get_template(template_path).render(flatten_context(context))
|
nautobot/core/urls.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
|
-
from django.http import HttpResponse, HttpResponseNotFound
|
|
3
2
|
from django.urls import include, path
|
|
4
3
|
from django.views.generic import TemplateView
|
|
5
4
|
from django.views.static import serve
|
|
@@ -10,6 +9,7 @@ from nautobot.core.views import (
|
|
|
10
9
|
HomeView,
|
|
11
10
|
NautobotMetricsView,
|
|
12
11
|
NautobotMetricsViewAuth,
|
|
12
|
+
RenderJinjaView,
|
|
13
13
|
SearchView,
|
|
14
14
|
StaticMediaFailureView,
|
|
15
15
|
ThemePreviewView,
|
|
@@ -42,6 +42,7 @@ urlpatterns = [
|
|
|
42
42
|
path("user/", include("nautobot.users.urls")),
|
|
43
43
|
path("users/", include("nautobot.users.urls", "users")),
|
|
44
44
|
path("virtualization/", include("nautobot.virtualization.urls")),
|
|
45
|
+
path("wireless/", include("nautobot.wireless.urls")),
|
|
45
46
|
# API
|
|
46
47
|
path("api/", include("nautobot.core.api.urls")),
|
|
47
48
|
# GraphQL
|
|
@@ -69,18 +70,12 @@ urlpatterns = [
|
|
|
69
70
|
),
|
|
70
71
|
# Celery worker status page
|
|
71
72
|
path("worker-status/", WorkerStatusView.as_view(), name="worker_status"),
|
|
73
|
+
# Jinja template renderer tool
|
|
74
|
+
path("render-jinja-template/", RenderJinjaView.as_view(), name="render_jinja_template"),
|
|
72
75
|
# Templated css file
|
|
73
76
|
path(
|
|
74
77
|
"template.css", TemplateView.as_view(template_name="template.css", content_type="text/css"), name="template_css"
|
|
75
78
|
),
|
|
76
|
-
# The response is conditional as opposed to wrapping the path() call in an if statement to be able to test the setting with current test setup
|
|
77
|
-
path(
|
|
78
|
-
"robots.txt",
|
|
79
|
-
lambda x: HttpResponse("User-Agent: *\nDisallow: /", content_type="text/plain")
|
|
80
|
-
if settings.PUBLISH_ROBOTS_TXT
|
|
81
|
-
else HttpResponseNotFound(),
|
|
82
|
-
name="robots_txt",
|
|
83
|
-
),
|
|
84
79
|
]
|
|
85
80
|
|
|
86
81
|
|
nautobot/core/utils/config.py
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
"""Helper code for loading values that may be defined in settings.py/nautobot_config.py *or* in django-constance."""
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
4
|
+
import logging
|
|
5
|
+
|
|
3
6
|
from constance import config
|
|
4
7
|
from django.conf import settings
|
|
8
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
9
|
+
from django.db import OperationalError, ProgrammingError
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
5
13
|
|
|
14
|
+
def get_settings_or_config(variable_name, fallback=None):
|
|
15
|
+
"""
|
|
16
|
+
Get a value from Django settings (if specified there) or Constance configuration (otherwise).
|
|
6
17
|
|
|
7
|
-
|
|
8
|
-
|
|
18
|
+
The fallback value is returned *only* if the requested variable cannot be found at all - this is an error case,
|
|
19
|
+
and will generate warning logs.
|
|
20
|
+
"""
|
|
9
21
|
# Explicitly set in settings.py or nautobot_config.py takes precedence, for now
|
|
10
22
|
if hasattr(settings, variable_name):
|
|
11
23
|
return getattr(settings, variable_name)
|
|
12
|
-
|
|
24
|
+
# django-constance 4.x removed some built-in error handling here, so we have to do it ourselves now
|
|
25
|
+
with contextlib.suppress(ObjectDoesNotExist, OperationalError, ProgrammingError):
|
|
26
|
+
return getattr(config, variable_name)
|
|
27
|
+
logger.warning(
|
|
28
|
+
'Configuration "%s" is not in settings, and could not read from the Constance database table '
|
|
29
|
+
"(perhaps not initialized yet?)",
|
|
30
|
+
variable_name,
|
|
31
|
+
)
|
|
32
|
+
if variable_name in settings.CONSTANCE_CONFIG:
|
|
33
|
+
default = settings.CONSTANCE_CONFIG[variable_name][0]
|
|
34
|
+
logger.warning('Using default value of "%s" from Constance configuration for "%s"', default, variable_name)
|
|
35
|
+
return default
|
|
36
|
+
logger.warning(
|
|
37
|
+
'Constance configuration does not include an entry for "%s" - must return %s', variable_name, fallback
|
|
38
|
+
)
|
|
39
|
+
return fallback
|
nautobot/core/utils/lookup.py
CHANGED
|
@@ -8,8 +8,9 @@ from django.conf import settings
|
|
|
8
8
|
from django.contrib.auth.models import Group
|
|
9
9
|
from django.contrib.contenttypes.models import ContentType
|
|
10
10
|
from django.db.models import Model
|
|
11
|
-
from django.urls import get_resolver,
|
|
11
|
+
from django.urls import get_resolver, URLPattern, URLResolver
|
|
12
12
|
from django.utils.module_loading import import_string
|
|
13
|
+
from django.views.generic.base import RedirectView
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def get_changes_for_model(model):
|
|
@@ -212,7 +213,7 @@ def get_related_field_for_models(from_model, to_model):
|
|
|
212
213
|
return matching_field
|
|
213
214
|
|
|
214
215
|
|
|
215
|
-
def get_table_for_model(model
|
|
216
|
+
def get_table_for_model(model):
|
|
216
217
|
"""Return the `Table` class associated with a given `model`.
|
|
217
218
|
|
|
218
219
|
The `Table` class is expected to be in the `tables` module within the application
|
|
@@ -222,12 +223,11 @@ def get_table_for_model(model, suffix=None):
|
|
|
222
223
|
|
|
223
224
|
Args:
|
|
224
225
|
model (BaseModel): A model class
|
|
225
|
-
suffix (str): A replacement suffix for the table name (e.g. `DetailTable`, such as to retrieve `FooDetailTable`)
|
|
226
226
|
|
|
227
227
|
Returns:
|
|
228
228
|
(Union[Table, None]): Either the `Table` class or `None`
|
|
229
229
|
"""
|
|
230
|
-
return get_related_class_for_model(model, module_name="tables", object_suffix=
|
|
230
|
+
return get_related_class_for_model(model, module_name="tables", object_suffix="Table")
|
|
231
231
|
|
|
232
232
|
|
|
233
233
|
def get_view_for_model(model, view_type=""):
|
|
@@ -276,13 +276,11 @@ def get_table_class_string_from_view_name(view_name):
|
|
|
276
276
|
Returns:
|
|
277
277
|
table_class_name (String): The name of the model table class or None e.g. LocationTable, CircuitTable
|
|
278
278
|
"""
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if hasattr(view_class, "table"):
|
|
285
|
-
return view_class.table.__name__
|
|
279
|
+
model = get_model_for_view_name(view_name)
|
|
280
|
+
if model:
|
|
281
|
+
table_class = get_table_for_model(model)
|
|
282
|
+
if table_class:
|
|
283
|
+
return table_class.__name__
|
|
286
284
|
return None
|
|
287
285
|
|
|
288
286
|
|
|
@@ -315,7 +313,7 @@ def get_created_and_last_updated_usernames_for_model(instance):
|
|
|
315
313
|
return created_by, last_updated_by
|
|
316
314
|
|
|
317
315
|
|
|
318
|
-
def get_url_patterns(urlconf=None, patterns_list=None, base_path="/"):
|
|
316
|
+
def get_url_patterns(urlconf=None, patterns_list=None, base_path="/", ignore_redirects=False):
|
|
319
317
|
"""
|
|
320
318
|
Recursively yield a list of registered URL patterns.
|
|
321
319
|
|
|
@@ -326,6 +324,7 @@ def get_url_patterns(urlconf=None, patterns_list=None, base_path="/"):
|
|
|
326
324
|
Default if unspecified is the `url_patterns` attribute of the given `urlconf` module.
|
|
327
325
|
base_path (str): String to prepend to all URL patterns yielded.
|
|
328
326
|
Default if unspecified is the string `"/"`.
|
|
327
|
+
ignore_redirects (bool): If True, skip URL patterns that correspond to RedirectViews.
|
|
329
328
|
|
|
330
329
|
Yields:
|
|
331
330
|
(str): Each URL pattern defined in the given urlconf and its descendants
|
|
@@ -384,10 +383,18 @@ def get_url_patterns(urlconf=None, patterns_list=None, base_path="/"):
|
|
|
384
383
|
|
|
385
384
|
for item in patterns_list:
|
|
386
385
|
if isinstance(item, URLPattern):
|
|
386
|
+
if (
|
|
387
|
+
ignore_redirects
|
|
388
|
+
and hasattr(item.callback, "view_class")
|
|
389
|
+
and issubclass(item.callback.view_class, RedirectView)
|
|
390
|
+
):
|
|
391
|
+
continue
|
|
387
392
|
yield base_path + str(item.pattern)
|
|
388
393
|
elif isinstance(item, URLResolver):
|
|
389
394
|
# Recurse!
|
|
390
|
-
yield from get_url_patterns(
|
|
395
|
+
yield from get_url_patterns(
|
|
396
|
+
urlconf, item.url_patterns, base_path + str(item.pattern), ignore_redirects=ignore_redirects
|
|
397
|
+
)
|
|
391
398
|
|
|
392
399
|
|
|
393
400
|
def get_url_for_url_pattern(url_pattern):
|
nautobot/core/views/__init__.py
CHANGED
|
@@ -56,7 +56,6 @@ logger = logging.getLogger(__name__)
|
|
|
56
56
|
|
|
57
57
|
class HomeView(AccessMixin, TemplateView):
|
|
58
58
|
template_name = "home.html"
|
|
59
|
-
use_new_ui = True
|
|
60
59
|
|
|
61
60
|
def render_additional_content(self, request, context, details):
|
|
62
61
|
# Collect all custom data using callback functions.
|
|
@@ -479,3 +478,9 @@ def get_file_with_authorization(request, *args, **kwargs):
|
|
|
479
478
|
get_object_or_404(queryset, file=request.GET.get("name"))
|
|
480
479
|
|
|
481
480
|
return get_file(request, *args, **kwargs)
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
class RenderJinjaView(LoginRequiredMixin, TemplateView):
|
|
484
|
+
"""Render a Jinja template with context data."""
|
|
485
|
+
|
|
486
|
+
template_name = "utilities/render_jinja2.html"
|
nautobot/core/views/generic.py
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
from __future__ import annotations # python 3.8
|
|
2
|
-
|
|
3
1
|
from copy import deepcopy
|
|
4
2
|
import logging
|
|
5
3
|
import re
|
|
6
|
-
from typing import Optional
|
|
7
4
|
|
|
8
5
|
from django.conf import settings
|
|
9
6
|
from django.contrib import messages
|
|
@@ -16,7 +13,7 @@ from django.core.exceptions import (
|
|
|
16
13
|
ValidationError,
|
|
17
14
|
)
|
|
18
15
|
from django.db import IntegrityError, transaction
|
|
19
|
-
from django.db.models import ManyToManyField,
|
|
16
|
+
from django.db.models import ManyToManyField, ProtectedError, Q
|
|
20
17
|
from django.forms import Form, ModelMultipleChoiceField, MultipleHiddenInput
|
|
21
18
|
from django.http import HttpResponse
|
|
22
19
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
@@ -25,10 +22,10 @@ from django.utils.encoding import iri_to_uri
|
|
|
25
22
|
from django.utils.html import format_html
|
|
26
23
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
27
24
|
from django.views.generic import View
|
|
28
|
-
from
|
|
29
|
-
from django_tables2 import RequestConfig, Table
|
|
25
|
+
from django_tables2 import RequestConfig
|
|
30
26
|
|
|
31
27
|
from nautobot.core.api.utils import get_serializer_for_model
|
|
28
|
+
from nautobot.core.constants import MAX_PAGE_SIZE_DEFAULT
|
|
32
29
|
from nautobot.core.exceptions import AbortTransaction
|
|
33
30
|
from nautobot.core.forms import (
|
|
34
31
|
BootstrapMixin,
|
|
@@ -82,8 +79,9 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
|
82
79
|
template_name: Name of the template to use
|
|
83
80
|
"""
|
|
84
81
|
|
|
85
|
-
queryset
|
|
86
|
-
template_name
|
|
82
|
+
queryset = None
|
|
83
|
+
template_name = None
|
|
84
|
+
object_detail_content = None
|
|
87
85
|
|
|
88
86
|
def get_required_permission(self):
|
|
89
87
|
return get_permission_for_model(self.queryset.model, "view")
|
|
@@ -123,6 +121,7 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
|
123
121
|
"content_type": content_type,
|
|
124
122
|
"verbose_name": self.queryset.model._meta.verbose_name,
|
|
125
123
|
"verbose_name_plural": self.queryset.model._meta.verbose_name_plural,
|
|
124
|
+
"object_detail_content": self.object_detail_content,
|
|
126
125
|
**common_detail_view_context(request, instance),
|
|
127
126
|
**self.get_extra_context(request, instance),
|
|
128
127
|
}
|
|
@@ -143,10 +142,10 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
143
142
|
non_filter_params: List of query parameters that are **not** used for queryset filtering
|
|
144
143
|
"""
|
|
145
144
|
|
|
146
|
-
queryset
|
|
147
|
-
filterset
|
|
148
|
-
filterset_form
|
|
149
|
-
table
|
|
145
|
+
queryset = None
|
|
146
|
+
filterset = None
|
|
147
|
+
filterset_form = None
|
|
148
|
+
table = None
|
|
150
149
|
template_name = "generic/object_list.html"
|
|
151
150
|
action_buttons = ("add", "import", "export")
|
|
152
151
|
non_filter_params = (
|
|
@@ -163,11 +162,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
163
162
|
def get_filter_params(self, request):
|
|
164
163
|
"""Helper function - take request.GET and discard any parameters that are not used for queryset filtering."""
|
|
165
164
|
params = request.GET.copy()
|
|
166
|
-
filter_params = get_filterable_params_from_filter_params(
|
|
167
|
-
params,
|
|
168
|
-
self.non_filter_params,
|
|
169
|
-
self.filterset(), # pylint: disable=not-callable # this fn is only called if filterset is not None
|
|
170
|
-
)
|
|
165
|
+
filter_params = get_filterable_params_from_filter_params(params, self.non_filter_params, self.filterset())
|
|
171
166
|
if params.get("saved_view") and not filter_params and not params.get("all_filters_removed"):
|
|
172
167
|
return SavedView.objects.get(pk=params.get("saved_view")).config.get("filter_params", {})
|
|
173
168
|
return filter_params
|
|
@@ -241,9 +236,9 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
241
236
|
except ObjectDoesNotExist:
|
|
242
237
|
pass
|
|
243
238
|
|
|
244
|
-
if self.filterset
|
|
239
|
+
if self.filterset:
|
|
245
240
|
filter_params = self.get_filter_params(request)
|
|
246
|
-
filterset = self.filterset(filter_params, self.queryset)
|
|
241
|
+
filterset = self.filterset(filter_params, self.queryset)
|
|
247
242
|
self.queryset = filterset.qs
|
|
248
243
|
if not filterset.is_valid():
|
|
249
244
|
messages.error(
|
|
@@ -271,7 +266,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
271
266
|
else:
|
|
272
267
|
dynamic_filter_form = DynamicFilterFormSet(filterset=filterset)
|
|
273
268
|
|
|
274
|
-
if self.filterset_form
|
|
269
|
+
if self.filterset_form:
|
|
275
270
|
filter_form = self.filterset_form(filter_params, label_suffix="")
|
|
276
271
|
|
|
277
272
|
# Check for export template rendering
|
|
@@ -331,14 +326,14 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
331
326
|
messages.error(request, f"Saved view {current_saved_view_pk} not found")
|
|
332
327
|
|
|
333
328
|
# Construct the objects table
|
|
334
|
-
if self.table
|
|
329
|
+
if self.table:
|
|
335
330
|
if self.request.GET.getlist("sort") or (
|
|
336
331
|
current_saved_view is not None and current_saved_view.config.get("sort_order")
|
|
337
332
|
):
|
|
338
333
|
hide_hierarchy_ui = True # hide tree hierarchy if custom sort is used
|
|
339
334
|
table_changes_pending = self.request.GET.get("table_changes_pending", False)
|
|
340
335
|
|
|
341
|
-
table = self.table(
|
|
336
|
+
table = self.table(
|
|
342
337
|
self.queryset,
|
|
343
338
|
table_changes_pending=table_changes_pending,
|
|
344
339
|
saved_view=current_saved_view,
|
|
@@ -355,7 +350,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
355
350
|
}
|
|
356
351
|
RequestConfig(request, paginate).configure(table)
|
|
357
352
|
table_config_form = TableConfigForm(table=table)
|
|
358
|
-
max_page_size = get_settings_or_config("MAX_PAGE_SIZE")
|
|
353
|
+
max_page_size = get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT)
|
|
359
354
|
if max_page_size and paginate["per_page"] > max_page_size:
|
|
360
355
|
messages.warning(
|
|
361
356
|
request,
|
|
@@ -415,8 +410,8 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
415
410
|
template_name: The name of the template
|
|
416
411
|
"""
|
|
417
412
|
|
|
418
|
-
queryset
|
|
419
|
-
model_form
|
|
413
|
+
queryset = None
|
|
414
|
+
model_form = None
|
|
420
415
|
template_name = "generic/object_create.html"
|
|
421
416
|
|
|
422
417
|
def get_required_permission(self):
|
|
@@ -558,7 +553,7 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
558
553
|
template_name: The name of the template
|
|
559
554
|
"""
|
|
560
555
|
|
|
561
|
-
queryset
|
|
556
|
+
queryset = None
|
|
562
557
|
template_name = "generic/object_delete.html"
|
|
563
558
|
|
|
564
559
|
def get_required_permission(self):
|
|
@@ -638,9 +633,9 @@ class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
638
633
|
template_name: The name of the template
|
|
639
634
|
"""
|
|
640
635
|
|
|
641
|
-
queryset
|
|
642
|
-
form
|
|
643
|
-
model_form
|
|
636
|
+
queryset = None
|
|
637
|
+
form = None
|
|
638
|
+
model_form = None
|
|
644
639
|
pattern_target = ""
|
|
645
640
|
template_name = None
|
|
646
641
|
|
|
@@ -747,8 +742,8 @@ class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
747
742
|
template_name: The name of the template
|
|
748
743
|
"""
|
|
749
744
|
|
|
750
|
-
queryset
|
|
751
|
-
model_form
|
|
745
|
+
queryset = None
|
|
746
|
+
model_form = None
|
|
752
747
|
related_object_forms = {}
|
|
753
748
|
template_name = "generic/object_import.html"
|
|
754
749
|
|
|
@@ -892,8 +887,8 @@ class BulkImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): #
|
|
|
892
887
|
template_name: The name of the template
|
|
893
888
|
"""
|
|
894
889
|
|
|
895
|
-
queryset
|
|
896
|
-
table
|
|
890
|
+
queryset = None
|
|
891
|
+
table = None
|
|
897
892
|
template_name = "generic/object_bulk_import.html"
|
|
898
893
|
|
|
899
894
|
def __init__(self, *args, **kwargs):
|
|
@@ -998,10 +993,10 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, EditAndDele
|
|
|
998
993
|
template_name: The name of the template
|
|
999
994
|
"""
|
|
1000
995
|
|
|
1001
|
-
queryset
|
|
1002
|
-
filterset
|
|
1003
|
-
table
|
|
1004
|
-
form
|
|
996
|
+
queryset = None
|
|
997
|
+
filterset = None
|
|
998
|
+
table = None
|
|
999
|
+
form = None
|
|
1005
1000
|
template_name = "generic/object_bulk_edit.html"
|
|
1006
1001
|
|
|
1007
1002
|
def get_required_permission(self):
|
|
@@ -1172,7 +1167,7 @@ class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
1172
1167
|
An extendable view for renaming objects in bulk.
|
|
1173
1168
|
"""
|
|
1174
1169
|
|
|
1175
|
-
queryset
|
|
1170
|
+
queryset = None
|
|
1176
1171
|
template_name = "generic/object_bulk_rename.html"
|
|
1177
1172
|
|
|
1178
1173
|
def __init__(self, *args, **kwargs):
|
|
@@ -1278,10 +1273,10 @@ class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, EditAndDe
|
|
|
1278
1273
|
template_name: The name of the template
|
|
1279
1274
|
"""
|
|
1280
1275
|
|
|
1281
|
-
queryset
|
|
1282
|
-
filterset
|
|
1283
|
-
table
|
|
1284
|
-
form
|
|
1276
|
+
queryset = None
|
|
1277
|
+
filterset = None
|
|
1278
|
+
table = None
|
|
1279
|
+
form = None
|
|
1285
1280
|
template_name = "generic/object_bulk_delete.html"
|
|
1286
1281
|
|
|
1287
1282
|
def get_required_permission(self):
|
|
@@ -1396,9 +1391,9 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
|
1396
1391
|
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
|
1397
1392
|
"""
|
|
1398
1393
|
|
|
1399
|
-
queryset
|
|
1400
|
-
form
|
|
1401
|
-
model_form
|
|
1394
|
+
queryset = None
|
|
1395
|
+
form = None
|
|
1396
|
+
model_form = None
|
|
1402
1397
|
template_name = "dcim/device_component_add.html"
|
|
1403
1398
|
|
|
1404
1399
|
def get_required_permission(self):
|
|
@@ -1498,13 +1493,13 @@ class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin,
|
|
|
1498
1493
|
Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines.
|
|
1499
1494
|
"""
|
|
1500
1495
|
|
|
1501
|
-
parent_model
|
|
1496
|
+
parent_model = None
|
|
1502
1497
|
parent_field = None
|
|
1503
|
-
form
|
|
1504
|
-
queryset
|
|
1505
|
-
model_form
|
|
1506
|
-
filterset
|
|
1507
|
-
table
|
|
1498
|
+
form = None
|
|
1499
|
+
queryset = None
|
|
1500
|
+
model_form = None
|
|
1501
|
+
filterset = None
|
|
1502
|
+
table = None
|
|
1508
1503
|
template_name = "generic/object_bulk_add_component.html"
|
|
1509
1504
|
|
|
1510
1505
|
def get_required_permission(self):
|
|
@@ -1518,7 +1513,7 @@ class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin,
|
|
|
1518
1513
|
|
|
1519
1514
|
# Are we editing *all* objects in the queryset or just a selected subset?
|
|
1520
1515
|
if request.POST.get("_all") and self.filterset is not None:
|
|
1521
|
-
pk_list = [obj.pk for obj in self.filterset(request.GET, self.parent_model.objects.only("pk")).qs]
|
|
1516
|
+
pk_list = [obj.pk for obj in self.filterset(request.GET, self.parent_model.objects.only("pk")).qs]
|
|
1522
1517
|
else:
|
|
1523
1518
|
pk_list = request.POST.getlist("pk")
|
|
1524
1519
|
|
nautobot/core/views/mixins.py
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
from __future__ import annotations # python 3.8
|
|
2
|
-
|
|
3
1
|
import logging
|
|
4
|
-
from typing import Optional
|
|
5
2
|
|
|
6
3
|
from django.contrib import messages
|
|
7
4
|
from django.contrib.auth.mixins import AccessMixin
|
|
@@ -25,7 +22,6 @@ from django.utils.encoding import iri_to_uri
|
|
|
25
22
|
from django.utils.html import format_html
|
|
26
23
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
27
24
|
from django.views.generic.edit import FormView
|
|
28
|
-
from django_filters import FilterSet
|
|
29
25
|
from drf_spectacular.utils import extend_schema
|
|
30
26
|
from rest_framework import exceptions, mixins
|
|
31
27
|
from rest_framework.decorators import action as drf_action
|
|
@@ -227,7 +223,7 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
|
|
|
227
223
|
# filterset and filter_params will be initialized in filter_queryset() in ObjectListViewMixin
|
|
228
224
|
filter_params = None
|
|
229
225
|
filterset = None
|
|
230
|
-
filterset_class
|
|
226
|
+
filterset_class = None
|
|
231
227
|
filterset_form_class = None
|
|
232
228
|
form_class = None
|
|
233
229
|
create_form_class = None
|
|
@@ -477,11 +473,7 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
|
|
|
477
473
|
def get_filter_params(self, request):
|
|
478
474
|
"""Helper function - take request.GET and discard any parameters that are not used for queryset filtering."""
|
|
479
475
|
params = request.GET.copy()
|
|
480
|
-
filter_params = get_filterable_params_from_filter_params(
|
|
481
|
-
params,
|
|
482
|
-
self.non_filter_params,
|
|
483
|
-
self.filterset_class(), # pylint: disable=not-callable # only called if filterset_class is not None
|
|
484
|
-
)
|
|
476
|
+
filter_params = get_filterable_params_from_filter_params(params, self.non_filter_params, self.filterset_class())
|
|
485
477
|
if params.get("saved_view") and not filter_params and not params.get("all_filters_removed"):
|
|
486
478
|
return SavedView.objects.get(pk=params.get("saved_view")).config.get("filter_params", {})
|
|
487
479
|
return filter_params
|
|
@@ -622,12 +614,13 @@ class ObjectDetailViewMixin(NautobotViewSetMixin, mixins.RetrieveModelMixin):
|
|
|
622
614
|
UI mixin to retrieve a model instance.
|
|
623
615
|
"""
|
|
624
616
|
|
|
617
|
+
object_detail_content = None
|
|
618
|
+
|
|
625
619
|
def retrieve(self, request, *args, **kwargs):
|
|
626
620
|
"""
|
|
627
621
|
Retrieve a model instance.
|
|
628
622
|
"""
|
|
629
|
-
|
|
630
|
-
return Response(context)
|
|
623
|
+
return Response({})
|
|
631
624
|
|
|
632
625
|
|
|
633
626
|
class ObjectListViewMixin(NautobotViewSetMixin, mixins.ListModelMixin):
|
|
@@ -636,8 +629,8 @@ class ObjectListViewMixin(NautobotViewSetMixin, mixins.ListModelMixin):
|
|
|
636
629
|
"""
|
|
637
630
|
|
|
638
631
|
action_buttons = ("add", "import", "export")
|
|
639
|
-
filterset_class
|
|
640
|
-
filterset_form_class
|
|
632
|
+
filterset_class = None
|
|
633
|
+
filterset_form_class = None
|
|
641
634
|
hide_hierarchy_ui = False
|
|
642
635
|
non_filter_params = (
|
|
643
636
|
"export", # trigger for CSV/export-template/YAML export # 3.0 TODO: remove, irrelevant after #4746
|
|
@@ -713,7 +706,6 @@ class ObjectListViewMixin(NautobotViewSetMixin, mixins.ListModelMixin):
|
|
|
713
706
|
"""
|
|
714
707
|
List the model instances.
|
|
715
708
|
"""
|
|
716
|
-
context = {"use_new_ui": True}
|
|
717
709
|
queryset = self.get_queryset()
|
|
718
710
|
clear_view = request.GET.get("clear_view", False)
|
|
719
711
|
if "export" in request.GET: # 3.0 TODO: remove, irrelevant after #4746
|
|
@@ -751,7 +743,7 @@ class ObjectListViewMixin(NautobotViewSetMixin, mixins.ListModelMixin):
|
|
|
751
743
|
except ObjectDoesNotExist:
|
|
752
744
|
pass
|
|
753
745
|
|
|
754
|
-
return Response(
|
|
746
|
+
return Response({})
|
|
755
747
|
|
|
756
748
|
|
|
757
749
|
class ObjectDestroyViewMixin(NautobotViewSetMixin, mixins.DestroyModelMixin):
|
|
@@ -788,8 +780,7 @@ class ObjectDestroyViewMixin(NautobotViewSetMixin, mixins.DestroyModelMixin):
|
|
|
788
780
|
return self.perform_destroy(request, **kwargs)
|
|
789
781
|
return Response(context)
|
|
790
782
|
|
|
791
|
-
|
|
792
|
-
def perform_destroy(self, request, **kwargs): # pylint:disable=arguments-renamed
|
|
783
|
+
def perform_destroy(self, request, **kwargs):
|
|
793
784
|
"""
|
|
794
785
|
Function to validate the ObjectDeleteConfirmationForm and to delete the object.
|
|
795
786
|
"""
|
|
@@ -943,7 +934,7 @@ class EditAndDeleteAllModelMixin:
|
|
|
943
934
|
filterset_class = getattr(self, "filterset_class", None)
|
|
944
935
|
|
|
945
936
|
if request.GET and filterset_class is not None:
|
|
946
|
-
queryset = filterset_class(request.GET, model.objects.all()).qs
|
|
937
|
+
queryset = filterset_class(request.GET, model.objects.all()).qs
|
|
947
938
|
# We take this approach because filterset.qs has already applied .distinct(),
|
|
948
939
|
# and performing a .delete directly on a queryset with .distinct applied is not allowed.
|
|
949
940
|
queryset = self.queryset.filter(pk__in=queryset)
|
|
@@ -967,8 +958,8 @@ class ObjectBulkDestroyViewMixin(NautobotViewSetMixin, BulkDestroyModelMixin, Ed
|
|
|
967
958
|
UI mixin to bulk destroy model instances.
|
|
968
959
|
"""
|
|
969
960
|
|
|
970
|
-
bulk_destroy_form_class
|
|
971
|
-
filterset_class
|
|
961
|
+
bulk_destroy_form_class = None
|
|
962
|
+
filterset_class = None
|
|
972
963
|
|
|
973
964
|
def _process_bulk_destroy_form(self, form):
|
|
974
965
|
request = self.request
|
|
@@ -1001,8 +992,7 @@ class ObjectBulkDestroyViewMixin(NautobotViewSetMixin, BulkDestroyModelMixin, Ed
|
|
|
1001
992
|
"""
|
|
1002
993
|
return self.perform_bulk_destroy(request, **kwargs)
|
|
1003
994
|
|
|
1004
|
-
|
|
1005
|
-
def perform_bulk_destroy(self, request, **kwargs): # pylint:disable=arguments-renamed
|
|
995
|
+
def perform_bulk_destroy(self, request, **kwargs):
|
|
1006
996
|
"""
|
|
1007
997
|
request.POST "_delete": Function to render the user selection of objects in a table form/BulkDestroyConfirmationForm via Response that is passed to NautobotHTMLRenderer.
|
|
1008
998
|
request.POST "_confirm": Function to validate the table form/BulkDestroyConfirmationForm and to perform the action of bulk destroy. Render the form with errors if exceptions are raised.
|
|
@@ -1097,8 +1087,8 @@ class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin, Edit
|
|
|
1097
1087
|
UI mixin to bulk update model instances.
|
|
1098
1088
|
"""
|
|
1099
1089
|
|
|
1100
|
-
filterset_class
|
|
1101
|
-
bulk_update_form_class
|
|
1090
|
+
filterset_class = None
|
|
1091
|
+
bulk_update_form_class = None
|
|
1102
1092
|
|
|
1103
1093
|
def _process_bulk_update_form(self, form):
|
|
1104
1094
|
request = self.request
|
nautobot/core/views/paginator.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.core.paginator import Page, Paginator
|
|
2
2
|
|
|
3
|
+
from nautobot.core.constants import MAX_PAGE_SIZE_DEFAULT, PAGINATE_COUNT_DEFAULT
|
|
3
4
|
from nautobot.core.utils import config
|
|
4
5
|
|
|
5
6
|
|
|
@@ -8,11 +9,11 @@ class EnhancedPaginator(Paginator):
|
|
|
8
9
|
try:
|
|
9
10
|
per_page = int(per_page)
|
|
10
11
|
if per_page < 1:
|
|
11
|
-
per_page = config.get_settings_or_config("PAGINATE_COUNT")
|
|
12
|
+
per_page = config.get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
|
|
12
13
|
except ValueError:
|
|
13
|
-
per_page = config.get_settings_or_config("PAGINATE_COUNT")
|
|
14
|
+
per_page = config.get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
|
|
14
15
|
|
|
15
|
-
max_page_size = config.get_settings_or_config("MAX_PAGE_SIZE")
|
|
16
|
+
max_page_size = config.get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT)
|
|
16
17
|
if max_page_size:
|
|
17
18
|
per_page = min(per_page, max_page_size)
|
|
18
19
|
|
|
@@ -65,5 +66,7 @@ def get_paginate_count(request, saved_view=None):
|
|
|
65
66
|
return per_page
|
|
66
67
|
|
|
67
68
|
if request.user.is_authenticated:
|
|
68
|
-
return request.user.get_config(
|
|
69
|
-
|
|
69
|
+
return request.user.get_config(
|
|
70
|
+
"pagination.per_page", config.get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
|
|
71
|
+
)
|
|
72
|
+
return config.get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
|