nautobot 2.3.15b1__py3-none-any.whl → 2.4.0__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.

Files changed (785) hide show
  1. nautobot/__init__.py +15 -0
  2. nautobot/apps/__init__.py +1 -1
  3. nautobot/apps/api.py +8 -10
  4. nautobot/apps/change_logging.py +2 -2
  5. nautobot/apps/choices.py +4 -4
  6. nautobot/apps/config.py +32 -3
  7. nautobot/apps/events.py +19 -0
  8. nautobot/apps/exceptions.py +0 -2
  9. nautobot/apps/factory.py +2 -2
  10. nautobot/apps/filters.py +1 -1
  11. nautobot/apps/forms.py +20 -20
  12. nautobot/apps/graphql.py +2 -2
  13. nautobot/apps/jobs.py +8 -8
  14. nautobot/apps/models.py +19 -19
  15. nautobot/apps/tables.py +1 -1
  16. nautobot/apps/testing.py +10 -10
  17. nautobot/apps/ui.py +44 -9
  18. nautobot/apps/utils.py +7 -15
  19. nautobot/apps/views.py +8 -6
  20. nautobot/circuits/api/serializers.py +1 -0
  21. nautobot/circuits/api/views.py +4 -8
  22. nautobot/circuits/navigation.py +0 -57
  23. nautobot/circuits/templates/circuits/circuit_create.html +1 -7
  24. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
  25. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
  26. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
  27. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
  28. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
  29. nautobot/circuits/tests/integration/test_relationships.py +33 -24
  30. nautobot/circuits/tests/test_filters.py +4 -8
  31. nautobot/circuits/views.py +143 -26
  32. nautobot/cloud/api/views.py +6 -10
  33. nautobot/cloud/factory.py +4 -1
  34. nautobot/cloud/models.py +1 -1
  35. nautobot/cloud/tests/test_filters.py +5 -4
  36. nautobot/cloud/views.py +0 -16
  37. nautobot/core/api/constants.py +11 -0
  38. nautobot/core/api/fields.py +5 -5
  39. nautobot/core/api/filter_backends.py +3 -9
  40. nautobot/core/api/metadata.py +28 -256
  41. nautobot/core/api/pagination.py +3 -2
  42. nautobot/core/api/renderers.py +3 -0
  43. nautobot/core/api/schema.py +13 -2
  44. nautobot/core/api/serializers.py +54 -268
  45. nautobot/core/api/urls.py +3 -4
  46. nautobot/core/api/utils.py +0 -62
  47. nautobot/core/api/views.py +102 -159
  48. nautobot/core/apps/__init__.py +22 -575
  49. nautobot/core/celery/__init__.py +13 -0
  50. nautobot/core/celery/schedulers.py +48 -3
  51. nautobot/core/choices.py +2 -2
  52. nautobot/core/cli/__init__.py +8 -0
  53. nautobot/core/constants.py +7 -0
  54. nautobot/core/events/__init__.py +116 -0
  55. nautobot/core/events/base.py +27 -0
  56. nautobot/core/events/exceptions.py +10 -0
  57. nautobot/core/events/redis_broker.py +48 -0
  58. nautobot/core/events/syslog_broker.py +19 -0
  59. nautobot/core/exceptions.py +0 -6
  60. nautobot/core/filters.py +19 -16
  61. nautobot/core/forms/__init__.py +19 -19
  62. nautobot/core/forms/fields.py +62 -14
  63. nautobot/core/forms/forms.py +33 -2
  64. nautobot/core/forms/utils.py +2 -1
  65. nautobot/core/graphql/schema.py +3 -1
  66. nautobot/core/graphql/types.py +1 -1
  67. nautobot/core/jobs/__init__.py +28 -7
  68. nautobot/core/jobs/bulk_actions.py +248 -0
  69. nautobot/core/jobs/cleanup.py +2 -2
  70. nautobot/core/jobs/groups.py +1 -1
  71. nautobot/core/management/commands/generate_test_data.py +21 -0
  72. nautobot/core/management/commands/validate_models.py +1 -1
  73. nautobot/core/middleware.py +16 -0
  74. nautobot/core/models/__init__.py +1 -1
  75. nautobot/core/models/fields.py +11 -7
  76. nautobot/core/models/query_functions.py +2 -2
  77. nautobot/core/models/tree_queries.py +2 -2
  78. nautobot/core/settings.py +71 -4
  79. nautobot/core/settings.yaml +107 -0
  80. nautobot/core/tables.py +15 -51
  81. nautobot/core/tasks.py +1 -1
  82. nautobot/core/templates/about.html +67 -0
  83. nautobot/core/templates/components/button/default.html +7 -0
  84. nautobot/core/templates/components/button/dropdown.html +20 -0
  85. nautobot/core/templates/components/layout/one_over_two.html +19 -0
  86. nautobot/core/templates/components/layout/two_over_one.html +19 -0
  87. nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
  88. nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
  89. nautobot/core/templates/components/panel/body_content_tags.html +6 -0
  90. nautobot/core/templates/components/panel/body_content_text.html +12 -0
  91. nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
  92. nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
  93. nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
  94. nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
  95. nautobot/core/templates/components/panel/footer_content_table.html +14 -0
  96. nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
  97. nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
  98. nautobot/core/templates/components/panel/panel.html +16 -0
  99. nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
  100. nautobot/core/templates/components/tab/content_wrapper.html +3 -0
  101. nautobot/core/templates/components/tab/label_wrapper.html +5 -0
  102. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
  103. nautobot/core/templates/generic/object_retrieve.html +28 -17
  104. nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
  105. nautobot/core/templates/inc/custom_fields/panel.html +2 -2
  106. nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
  107. nautobot/core/templates/inc/footer.html +1 -0
  108. nautobot/core/templates/inc/media.html +3 -0
  109. nautobot/core/templates/inc/nav_menu.html +2 -1
  110. nautobot/core/templates/inc/relationships_panel.html +1 -1
  111. nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
  112. nautobot/core/templates/inc/tenant_table_row.html +11 -0
  113. nautobot/core/templates/nautobot_config.py.j2 +16 -0
  114. nautobot/core/templates/panel_table.html +12 -0
  115. nautobot/core/templates/utilities/render_jinja2.html +117 -0
  116. nautobot/core/templates/utilities/templatetags/tag.html +1 -1
  117. nautobot/core/templates/utilities/theme_preview.html +7 -0
  118. nautobot/core/templatetags/helpers.py +104 -6
  119. nautobot/core/templatetags/ui_framework.py +40 -0
  120. nautobot/core/testing/__init__.py +8 -8
  121. nautobot/core/testing/api.py +187 -137
  122. nautobot/core/testing/context.py +18 -0
  123. nautobot/core/testing/filters.py +44 -34
  124. nautobot/core/testing/forms.py +2 -0
  125. nautobot/core/testing/views.py +68 -146
  126. nautobot/core/tests/integration/test_app_home.py +0 -1
  127. nautobot/core/tests/integration/test_app_navbar.py +0 -1
  128. nautobot/core/tests/integration/test_filters.py +0 -2
  129. nautobot/core/tests/integration/test_home.py +0 -1
  130. nautobot/core/tests/integration/test_navbar.py +0 -1
  131. nautobot/core/tests/integration/test_view_authentication.py +2 -1
  132. nautobot/core/tests/nautobot_config.py +198 -0
  133. nautobot/core/tests/runner.py +3 -3
  134. nautobot/core/tests/test_api.py +154 -176
  135. nautobot/core/tests/test_events.py +214 -0
  136. nautobot/core/tests/test_forms.py +1 -0
  137. nautobot/core/tests/test_jinja_filters.py +1 -0
  138. nautobot/core/tests/test_jobs.py +387 -14
  139. nautobot/core/tests/test_navigations.py +7 -241
  140. nautobot/core/tests/test_settings_schema.py +7 -0
  141. nautobot/core/tests/test_tables.py +100 -0
  142. nautobot/core/tests/test_templatetags_helpers.py +16 -0
  143. nautobot/core/tests/test_ui.py +150 -0
  144. nautobot/core/tests/test_utils.py +55 -18
  145. nautobot/core/tests/test_views.py +153 -5
  146. nautobot/core/ui/__init__.py +0 -0
  147. nautobot/core/ui/base.py +11 -0
  148. nautobot/core/ui/choices.py +44 -0
  149. nautobot/core/ui/homepage.py +167 -0
  150. nautobot/core/ui/nav.py +280 -0
  151. nautobot/core/ui/object_detail.py +1855 -0
  152. nautobot/core/ui/utils.py +36 -0
  153. nautobot/core/urls.py +15 -0
  154. nautobot/core/utils/config.py +30 -3
  155. nautobot/core/utils/lookup.py +12 -2
  156. nautobot/core/utils/querysets.py +64 -0
  157. nautobot/core/utils/requests.py +24 -9
  158. nautobot/core/views/__init__.py +48 -1
  159. nautobot/core/views/generic.py +82 -177
  160. nautobot/core/views/mixins.py +98 -38
  161. nautobot/core/views/paginator.py +8 -5
  162. nautobot/core/views/renderers.py +9 -9
  163. nautobot/core/views/utils.py +11 -0
  164. nautobot/core/wsgi.py +3 -3
  165. nautobot/dcim/api/serializers.py +82 -189
  166. nautobot/dcim/api/urls.py +5 -0
  167. nautobot/dcim/api/views.py +57 -110
  168. nautobot/dcim/apps.py +1 -0
  169. nautobot/dcim/choices.py +28 -0
  170. nautobot/dcim/factory.py +58 -0
  171. nautobot/dcim/filters/__init__.py +204 -2
  172. nautobot/dcim/forms.py +221 -9
  173. nautobot/dcim/graphql/types.py +2 -2
  174. nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
  175. nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
  176. nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
  177. nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
  178. nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
  179. nautobot/dcim/models/__init__.py +5 -1
  180. nautobot/dcim/models/device_component_templates.py +2 -2
  181. nautobot/dcim/models/device_components.py +22 -20
  182. nautobot/dcim/models/devices.py +181 -3
  183. nautobot/dcim/models/locations.py +3 -3
  184. nautobot/dcim/models/power.py +6 -5
  185. nautobot/dcim/models/racks.py +6 -6
  186. nautobot/dcim/navigation.py +25 -224
  187. nautobot/dcim/signals.py +44 -0
  188. nautobot/dcim/tables/__init__.py +5 -3
  189. nautobot/dcim/tables/devices.py +103 -7
  190. nautobot/dcim/tables/devicetypes.py +2 -2
  191. nautobot/dcim/tables/racks.py +1 -1
  192. nautobot/dcim/templates/dcim/controller/base.html +10 -0
  193. nautobot/dcim/templates/dcim/controller_create.html +2 -7
  194. nautobot/dcim/templates/dcim/controller_retrieve.html +6 -10
  195. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
  196. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -0
  197. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +51 -0
  198. nautobot/dcim/templates/dcim/device/base.html +6 -42
  199. nautobot/dcim/templates/dcim/device/wireless.html +73 -0
  200. nautobot/dcim/templates/dcim/device.html +4 -10
  201. nautobot/dcim/templates/dcim/device_edit.html +36 -37
  202. nautobot/dcim/templates/dcim/interface.html +1 -0
  203. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  204. nautobot/dcim/templates/dcim/location.html +1 -9
  205. nautobot/dcim/templates/dcim/location_edit.html +1 -7
  206. nautobot/dcim/templates/dcim/locationtype.html +0 -107
  207. nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
  208. nautobot/dcim/templates/dcim/rack.html +1 -9
  209. nautobot/dcim/templates/dcim/rack_edit.html +1 -7
  210. nautobot/dcim/templates/dcim/rackreservation.html +1 -9
  211. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +68 -0
  212. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +28 -0
  213. nautobot/dcim/tests/integration/test_controller.py +62 -0
  214. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
  215. nautobot/dcim/tests/test_api.py +188 -64
  216. nautobot/dcim/tests/test_filters.py +172 -76
  217. nautobot/dcim/tests/test_graphql.py +52 -0
  218. nautobot/dcim/tests/test_jobs.py +118 -0
  219. nautobot/dcim/tests/test_models.py +159 -5
  220. nautobot/dcim/tests/test_signals.py +1 -0
  221. nautobot/dcim/tests/test_views.py +118 -88
  222. nautobot/dcim/urls.py +72 -27
  223. nautobot/dcim/utils.py +2 -2
  224. nautobot/dcim/views.py +357 -62
  225. nautobot/extras/api/customfields.py +2 -2
  226. nautobot/extras/api/serializers.py +111 -87
  227. nautobot/extras/api/urls.py +4 -0
  228. nautobot/extras/api/views.py +93 -35
  229. nautobot/extras/choices.py +13 -0
  230. nautobot/extras/constants.py +2 -1
  231. nautobot/extras/context_managers.py +23 -6
  232. nautobot/extras/datasources/git.py +4 -1
  233. nautobot/extras/factory.py +27 -0
  234. nautobot/extras/filters/__init__.py +66 -5
  235. nautobot/extras/forms/base.py +2 -2
  236. nautobot/extras/forms/forms.py +262 -59
  237. nautobot/extras/forms/mixins.py +3 -3
  238. nautobot/extras/graphql/types.py +25 -1
  239. nautobot/extras/health_checks.py +1 -2
  240. nautobot/extras/jobs.py +114 -20
  241. nautobot/extras/management/__init__.py +1 -0
  242. nautobot/extras/management/commands/runjob.py +7 -79
  243. nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
  244. nautobot/extras/management/utils.py +87 -0
  245. nautobot/extras/managers.py +3 -1
  246. nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
  247. nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
  248. nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
  249. nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
  250. nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
  251. nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
  252. nautobot/extras/models/__init__.py +5 -1
  253. nautobot/extras/models/change_logging.py +7 -3
  254. nautobot/extras/models/contacts.py +1 -1
  255. nautobot/extras/models/customfields.py +12 -11
  256. nautobot/extras/models/groups.py +11 -9
  257. nautobot/extras/models/jobs.py +237 -37
  258. nautobot/extras/models/models.py +2 -2
  259. nautobot/extras/models/relationships.py +69 -1
  260. nautobot/extras/models/secrets.py +5 -0
  261. nautobot/extras/navigation.py +20 -262
  262. nautobot/extras/plugins/__init__.py +54 -19
  263. nautobot/extras/plugins/marketplace_manifest.yml +455 -0
  264. nautobot/extras/plugins/tables.py +16 -14
  265. nautobot/extras/plugins/urls.py +1 -0
  266. nautobot/extras/plugins/views.py +104 -61
  267. nautobot/extras/registry.py +1 -1
  268. nautobot/extras/secrets/__init__.py +2 -2
  269. nautobot/extras/signals.py +39 -1
  270. nautobot/extras/tables.py +42 -6
  271. nautobot/extras/templates/extras/dynamicgroup.html +1 -9
  272. nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
  273. nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
  274. nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
  275. nautobot/extras/templates/extras/job_detail.html +52 -6
  276. nautobot/extras/templates/extras/job_edit.html +6 -2
  277. nautobot/extras/templates/extras/job_list.html +2 -7
  278. nautobot/extras/templates/extras/jobqueue_retrieve.html +36 -0
  279. nautobot/extras/templates/extras/marketplace.html +296 -0
  280. nautobot/extras/templates/extras/plugin_detail.html +32 -15
  281. nautobot/extras/templates/extras/plugins_list.html +35 -1
  282. nautobot/extras/templates/extras/plugins_tiles.html +90 -0
  283. nautobot/extras/templates/extras/role_retrieve.html +16 -0
  284. nautobot/extras/templates/extras/secret.html +0 -65
  285. nautobot/extras/templates/extras/secret_check.js +16 -0
  286. nautobot/extras/templates/extras/secret_create.html +114 -0
  287. nautobot/extras/templates/extras/secret_edit.html +1 -114
  288. nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
  289. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
  290. nautobot/extras/templatetags/job_buttons.py +5 -4
  291. nautobot/extras/templatetags/plugins.py +69 -6
  292. nautobot/extras/test_jobs/api_test_job.py +1 -1
  293. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  294. nautobot/extras/test_jobs/dry_run.py +1 -1
  295. nautobot/extras/test_jobs/fail.py +5 -5
  296. nautobot/extras/test_jobs/file_output.py +1 -1
  297. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  298. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  299. nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
  300. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  301. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  302. nautobot/extras/test_jobs/log_redaction.py +1 -1
  303. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  304. nautobot/extras/test_jobs/modify_db.py +1 -1
  305. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  306. nautobot/extras/test_jobs/object_var_required.py +1 -1
  307. nautobot/extras/test_jobs/object_vars.py +1 -1
  308. nautobot/extras/test_jobs/pass.py +3 -3
  309. nautobot/extras/test_jobs/profiling.py +1 -1
  310. nautobot/extras/test_jobs/relative_import.py +3 -3
  311. nautobot/extras/test_jobs/singleton.py +16 -0
  312. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  313. nautobot/extras/test_jobs/task_queues.py +1 -1
  314. nautobot/extras/tests/integration/test_plugin_banner.py +0 -2
  315. nautobot/extras/tests/test_api.py +157 -55
  316. nautobot/extras/tests/test_context_managers.py +4 -1
  317. nautobot/extras/tests/test_customfields.py +1 -1
  318. nautobot/extras/tests/test_datasources.py +2 -1
  319. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  320. nautobot/extras/tests/test_filters.py +219 -535
  321. nautobot/extras/tests/test_forms.py +20 -1
  322. nautobot/extras/tests/test_job_variables.py +73 -152
  323. nautobot/extras/tests/test_jobs.py +192 -62
  324. nautobot/extras/tests/test_models.py +71 -16
  325. nautobot/extras/tests/test_plugins.py +62 -9
  326. nautobot/extras/tests/test_relationships.py +124 -10
  327. nautobot/extras/tests/test_utils.py +23 -2
  328. nautobot/extras/tests/test_views.py +162 -161
  329. nautobot/extras/tests/test_webhooks.py +2 -1
  330. nautobot/extras/urls.py +2 -20
  331. nautobot/extras/utils.py +119 -4
  332. nautobot/extras/views.py +188 -141
  333. nautobot/extras/webhooks.py +5 -2
  334. nautobot/ipam/api/fields.py +3 -3
  335. nautobot/ipam/api/serializers.py +44 -137
  336. nautobot/ipam/api/views.py +68 -110
  337. nautobot/ipam/factory.py +1 -1
  338. nautobot/ipam/filters.py +3 -2
  339. nautobot/ipam/models.py +10 -12
  340. nautobot/ipam/navigation.py +0 -90
  341. nautobot/ipam/querysets.py +2 -2
  342. nautobot/ipam/tables.py +3 -1
  343. nautobot/ipam/templates/ipam/ipaddress.html +1 -9
  344. nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +1 -7
  345. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -7
  346. nautobot/ipam/templates/ipam/prefix.html +1 -9
  347. nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
  348. nautobot/ipam/templates/ipam/routetarget.html +0 -28
  349. nautobot/ipam/templates/ipam/vlan.html +1 -9
  350. nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
  351. nautobot/ipam/templates/ipam/vrf.html +0 -47
  352. nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
  353. nautobot/ipam/tests/test_api.py +19 -6
  354. nautobot/ipam/tests/test_filters.py +39 -119
  355. nautobot/ipam/tests/test_forms.py +49 -47
  356. nautobot/ipam/tests/test_migrations.py +30 -30
  357. nautobot/ipam/tests/test_models.py +56 -36
  358. nautobot/ipam/tests/test_querysets.py +14 -0
  359. nautobot/ipam/tests/test_views.py +3 -0
  360. nautobot/ipam/urls.py +3 -69
  361. nautobot/ipam/utils/__init__.py +16 -10
  362. nautobot/ipam/views.py +91 -162
  363. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  364. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  365. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
  366. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  367. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  368. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  369. nautobot/project-static/css/base.css +38 -3
  370. nautobot/project-static/docs/404.html +463 -19
  371. nautobot/project-static/docs/apps/index.html +463 -19
  372. nautobot/project-static/docs/apps/nautobot-apps.html +464 -21
  373. nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
  374. nautobot/project-static/docs/assets/extra.css +5 -1
  375. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.88dd0f4e.min.js} +2 -2
  376. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.88dd0f4e.min.js.map} +2 -2
  377. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +479 -25
  378. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +476 -22
  379. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +792 -291
  380. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +507 -33
  381. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +512 -36
  382. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +473 -22
  383. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +469 -20
  384. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +499 -35
  385. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9883 -0
  386. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +525 -77
  387. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +548 -53
  388. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +672 -96
  389. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1033 -180
  390. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +526 -51
  391. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +876 -190
  392. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +957 -237
  393. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +477 -23
  394. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +488 -30
  395. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +663 -101
  396. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +949 -481
  397. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6427 -1236
  398. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +476 -22
  399. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +879 -346
  400. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +830 -173
  401. nautobot/project-static/docs/development/apps/api/configuration-view.html +463 -19
  402. nautobot/project-static/docs/development/apps/api/database-backend-config.html +463 -19
  403. nautobot/project-static/docs/development/apps/api/models/django-admin.html +463 -19
  404. nautobot/project-static/docs/development/apps/api/models/global-search.html +463 -19
  405. nautobot/project-static/docs/development/apps/api/models/graphql.html +463 -19
  406. nautobot/project-static/docs/development/apps/api/models/index.html +463 -19
  407. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +463 -19
  408. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +463 -19
  409. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +463 -19
  410. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +463 -19
  411. nautobot/project-static/docs/development/apps/api/platform-features/index.html +463 -19
  412. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +463 -19
  413. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +463 -19
  414. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +463 -19
  415. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +463 -19
  416. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +463 -19
  417. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +463 -19
  418. nautobot/project-static/docs/development/apps/api/prometheus.html +463 -19
  419. nautobot/project-static/docs/development/apps/api/setup.html +467 -155
  420. nautobot/project-static/docs/development/apps/api/testing.html +463 -19
  421. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +463 -19
  422. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +463 -19
  423. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +463 -19
  424. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +463 -19
  425. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +743 -130
  426. nautobot/project-static/docs/development/apps/api/views/base-template.html +463 -19
  427. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +463 -19
  428. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +463 -19
  429. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +463 -19
  430. nautobot/project-static/docs/development/apps/api/views/index.html +465 -20
  431. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +467 -19
  432. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +493 -19
  433. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +463 -19
  434. nautobot/project-static/docs/development/apps/api/views/notes.html +463 -19
  435. nautobot/project-static/docs/development/apps/api/views/rest-api.html +469 -21
  436. nautobot/project-static/docs/development/apps/api/views/urls.html +463 -19
  437. nautobot/project-static/docs/development/apps/index.html +463 -19
  438. nautobot/project-static/docs/development/apps/migration/code-updates.html +464 -52
  439. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +464 -20
  440. nautobot/project-static/docs/development/apps/migration/from-v1.html +463 -19
  441. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +463 -19
  442. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +463 -19
  443. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +463 -19
  444. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +466 -22
  445. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9261 -0
  446. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9375 -0
  447. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9671 -0
  448. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9559 -0
  449. nautobot/project-static/docs/development/apps/porting-from-netbox.html +466 -22
  450. nautobot/project-static/docs/development/core/application-registry.html +463 -19
  451. nautobot/project-static/docs/development/core/best-practices.html +463 -19
  452. nautobot/project-static/docs/development/core/bootstrap-ui.html +463 -19
  453. nautobot/project-static/docs/development/core/caching.html +463 -19
  454. nautobot/project-static/docs/development/core/controllers.html +465 -19
  455. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +491 -90
  456. nautobot/project-static/docs/development/core/generic-views.html +463 -19
  457. nautobot/project-static/docs/development/core/getting-started.html +541 -129
  458. nautobot/project-static/docs/development/core/homepage.html +474 -30
  459. nautobot/project-static/docs/development/core/index.html +463 -19
  460. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9754 -0
  461. nautobot/project-static/docs/development/core/model-checklist.html +473 -27
  462. nautobot/project-static/docs/development/core/model-features.html +463 -19
  463. nautobot/project-static/docs/development/core/natural-keys.html +463 -19
  464. nautobot/project-static/docs/development/core/navigation-menu.html +480 -26
  465. nautobot/project-static/docs/development/core/release-checklist.html +480 -48
  466. nautobot/project-static/docs/development/core/role-internals.html +463 -19
  467. nautobot/project-static/docs/development/core/settings.html +463 -19
  468. nautobot/project-static/docs/development/core/style-guide.html +466 -22
  469. nautobot/project-static/docs/development/core/templates.html +473 -22
  470. nautobot/project-static/docs/development/core/testing.html +463 -19
  471. nautobot/project-static/docs/development/core/ui-component-framework.html +11116 -0
  472. nautobot/project-static/docs/development/core/user-preferences.html +466 -22
  473. nautobot/project-static/docs/development/index.html +463 -19
  474. nautobot/project-static/docs/development/jobs/index.html +501 -21
  475. nautobot/project-static/docs/development/jobs/migration/from-v1.html +463 -19
  476. nautobot/project-static/docs/index.html +471 -38
  477. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
  478. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
  479. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
  480. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
  481. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
  482. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
  483. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
  484. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
  485. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
  486. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
  487. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
  488. nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
  489. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
  490. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
  491. nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
  492. nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
  493. nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
  494. nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
  495. nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
  496. nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
  497. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
  498. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
  499. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
  500. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
  501. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
  502. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
  503. nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
  504. nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
  505. nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
  506. nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
  507. nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
  508. nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
  509. nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
  510. nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
  511. nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
  512. nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
  513. nautobot/project-static/docs/objects.inv +0 -0
  514. nautobot/project-static/docs/overview/application_stack.html +469 -23
  515. nautobot/project-static/docs/overview/design_philosophy.html +463 -19
  516. nautobot/project-static/docs/release-notes/index.html +485 -22
  517. nautobot/project-static/docs/release-notes/version-1.0.html +651 -208
  518. nautobot/project-static/docs/release-notes/version-1.1.html +648 -205
  519. nautobot/project-static/docs/release-notes/version-1.2.html +723 -280
  520. nautobot/project-static/docs/release-notes/version-1.3.html +749 -306
  521. nautobot/project-static/docs/release-notes/version-1.4.html +834 -392
  522. nautobot/project-static/docs/release-notes/version-1.5.html +1022 -581
  523. nautobot/project-static/docs/release-notes/version-1.6.html +942 -518
  524. nautobot/project-static/docs/release-notes/version-2.0.html +945 -504
  525. nautobot/project-static/docs/release-notes/version-2.1.html +780 -339
  526. nautobot/project-static/docs/release-notes/version-2.2.html +773 -332
  527. nautobot/project-static/docs/release-notes/version-2.3.html +1142 -448
  528. nautobot/project-static/docs/release-notes/version-2.4.html +10323 -0
  529. nautobot/project-static/docs/requirements.txt +2 -2
  530. nautobot/project-static/docs/search/search_index.json +1 -1
  531. nautobot/project-static/docs/sitemap.xml +342 -270
  532. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  533. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +463 -19
  534. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +463 -19
  535. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +463 -19
  536. nautobot/project-static/docs/user-guide/administration/configuration/index.html +475 -32
  537. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +463 -19
  538. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +894 -180
  539. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +463 -19
  540. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +463 -19
  541. nautobot/project-static/docs/user-guide/administration/guides/docker.html +476 -29
  542. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +463 -19
  543. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +463 -19
  544. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +463 -19
  545. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +463 -19
  546. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +463 -19
  547. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +465 -21
  548. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +463 -19
  549. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +463 -19
  550. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +463 -19
  551. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +483 -23
  552. nautobot/project-static/docs/user-guide/administration/installation/index.html +468 -20
  553. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +464 -20
  554. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +463 -19
  555. nautobot/project-static/docs/user-guide/administration/installation/services.html +463 -19
  556. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +463 -19
  557. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +484 -41
  558. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +477 -66
  559. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +477 -66
  560. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +463 -19
  561. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +463 -19
  562. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +463 -19
  563. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +463 -19
  564. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +463 -19
  565. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +466 -23
  566. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +463 -19
  567. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
  568. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +463 -19
  569. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +469 -21
  570. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +463 -19
  571. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +463 -19
  572. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +463 -19
  573. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +463 -19
  574. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +463 -19
  575. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +463 -19
  576. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +463 -19
  577. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +463 -19
  578. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +463 -19
  579. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +463 -19
  580. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +463 -19
  581. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +463 -19
  582. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +463 -19
  583. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +463 -19
  584. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +463 -19
  585. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +463 -19
  586. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +463 -19
  587. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +499 -20
  588. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +489 -22
  589. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +463 -19
  590. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +463 -19
  591. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +463 -19
  592. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +463 -19
  593. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +463 -19
  594. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +463 -19
  595. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +463 -19
  596. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +463 -19
  597. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +463 -19
  598. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +463 -19
  599. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +463 -19
  600. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +463 -19
  601. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +463 -19
  602. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +463 -19
  603. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +463 -19
  604. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +463 -19
  605. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +463 -19
  606. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +463 -19
  607. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +463 -19
  608. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +463 -19
  609. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +463 -19
  610. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +463 -19
  611. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +463 -19
  612. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +463 -19
  613. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +463 -19
  614. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +463 -19
  615. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +463 -19
  616. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +463 -19
  617. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +463 -19
  618. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +463 -19
  619. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +463 -19
  620. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +463 -19
  621. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +463 -19
  622. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +463 -19
  623. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9375 -0
  624. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +470 -30
  625. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +463 -19
  626. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +463 -19
  627. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +463 -19
  628. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +463 -19
  629. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +463 -19
  630. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +463 -19
  631. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +463 -19
  632. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +463 -19
  633. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +463 -19
  634. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +463 -19
  635. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +463 -19
  636. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +463 -19
  637. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +466 -22
  638. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +463 -19
  639. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +463 -19
  640. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +463 -19
  641. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +463 -19
  642. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +463 -19
  643. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +463 -19
  644. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +466 -22
  645. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9313 -0
  646. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9217 -0
  647. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9211 -0
  648. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9277 -0
  649. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +463 -19
  650. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +463 -19
  651. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +463 -19
  652. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +463 -19
  653. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +463 -19
  654. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +463 -19
  655. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +463 -19
  656. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +463 -19
  657. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +463 -19
  658. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +463 -19
  659. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +463 -19
  660. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +468 -22
  661. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +463 -19
  662. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
  663. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
  664. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
  665. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
  666. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
  667. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
  668. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
  669. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
  670. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
  671. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
  672. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
  673. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
  674. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
  675. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +463 -19
  676. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +463 -19
  677. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +466 -22
  678. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9444 -0
  679. nautobot/project-static/docs/user-guide/index.html +463 -19
  680. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +466 -22
  681. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +467 -23
  682. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +463 -19
  683. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +463 -19
  684. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +463 -19
  685. nautobot/project-static/docs/user-guide/platform-functionality/events.html +9617 -0
  686. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +466 -22
  687. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +463 -19
  688. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +463 -19
  689. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +463 -19
  690. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +463 -19
  691. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +463 -19
  692. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +472 -23
  693. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +466 -22
  694. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +466 -22
  695. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +463 -19
  696. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9224 -0
  697. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9722 -0
  698. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +466 -22
  699. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +463 -19
  700. nautobot/project-static/docs/user-guide/platform-functionality/note.html +463 -19
  701. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +463 -19
  702. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +467 -23
  703. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9292 -0
  704. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +463 -19
  705. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +511 -40
  706. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +494 -23
  707. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +463 -19
  708. nautobot/project-static/docs/user-guide/platform-functionality/role.html +463 -19
  709. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +463 -19
  710. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +463 -19
  711. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +466 -22
  712. nautobot/project-static/docs/user-guide/platform-functionality/status.html +463 -19
  713. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +463 -19
  714. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +531 -56
  715. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +463 -19
  716. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +463 -19
  717. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +463 -19
  718. nautobot/project-static/img/jinja_logo.svg +97 -0
  719. nautobot/project-static/js/forms.js +6 -1
  720. nautobot/project-static/js/nav_menu.js +2 -1
  721. nautobot/tenancy/api/serializers.py +0 -2
  722. nautobot/tenancy/api/views.py +9 -13
  723. nautobot/tenancy/factory.py +1 -1
  724. nautobot/tenancy/navigation.py +0 -29
  725. nautobot/tenancy/templates/tenancy/tenant.html +4 -91
  726. nautobot/tenancy/tests/test_filters.py +29 -134
  727. nautobot/tenancy/views.py +35 -24
  728. nautobot/users/admin.py +3 -1
  729. nautobot/users/api/serializers.py +4 -4
  730. nautobot/users/api/views.py +3 -3
  731. nautobot/users/forms.py +19 -0
  732. nautobot/users/templates/users/preferences.html +22 -0
  733. nautobot/users/tests/test_filters.py +1 -19
  734. nautobot/users/tests/test_views.py +57 -0
  735. nautobot/users/utils.py +8 -0
  736. nautobot/users/views.py +48 -11
  737. nautobot/virtualization/api/serializers.py +4 -4
  738. nautobot/virtualization/api/views.py +5 -24
  739. nautobot/virtualization/filters.py +1 -2
  740. nautobot/virtualization/models.py +1 -1
  741. nautobot/virtualization/navigation.py +0 -48
  742. nautobot/virtualization/tables.py +2 -2
  743. nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
  744. nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
  745. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -9
  746. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
  747. nautobot/virtualization/tests/test_filters.py +57 -166
  748. nautobot/virtualization/views.py +18 -15
  749. nautobot/wireless/__init__.py +0 -0
  750. nautobot/wireless/api/__init__.py +0 -0
  751. nautobot/wireless/api/serializers.py +44 -0
  752. nautobot/wireless/api/urls.py +20 -0
  753. nautobot/wireless/api/views.py +34 -0
  754. nautobot/wireless/apps.py +8 -0
  755. nautobot/wireless/choices.py +345 -0
  756. nautobot/wireless/factory.py +138 -0
  757. nautobot/wireless/filters.py +167 -0
  758. nautobot/wireless/forms.py +283 -0
  759. nautobot/wireless/homepage.py +19 -0
  760. nautobot/wireless/migrations/0001_initial.py +223 -0
  761. nautobot/wireless/migrations/__init__.py +0 -0
  762. nautobot/wireless/models.py +207 -0
  763. nautobot/wireless/navigation.py +105 -0
  764. nautobot/wireless/tables.py +244 -0
  765. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
  766. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
  767. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
  768. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +56 -0
  769. nautobot/wireless/tests/__init__.py +0 -0
  770. nautobot/wireless/tests/integration/__init__.py +0 -0
  771. nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
  772. nautobot/wireless/tests/test_api.py +247 -0
  773. nautobot/wireless/tests/test_filters.py +82 -0
  774. nautobot/wireless/tests/test_models.py +22 -0
  775. nautobot/wireless/tests/test_views.py +378 -0
  776. nautobot/wireless/urls.py +13 -0
  777. nautobot/wireless/views.py +119 -0
  778. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/METADATA +11 -13
  779. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/RECORD +783 -613
  780. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/WHEEL +1 -1
  781. nautobot/core/fixtures/user-data.json +0 -59
  782. nautobot/core/utils/navigation.py +0 -54
  783. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/LICENSE.txt +0 -0
  784. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/NOTICE +0 -0
  785. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/entry_points.txt +0 -0
@@ -42,7 +42,6 @@ class NamespaceSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
42
42
  class Meta:
43
43
  model = Namespace
44
44
  fields = "__all__"
45
- list_display_fields = ["name", "description", "location"]
46
45
 
47
46
 
48
47
  #
@@ -54,7 +53,6 @@ class VRFSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
54
53
  class Meta:
55
54
  model = VRF
56
55
  fields = "__all__"
57
- list_display_fields = ["name", "rd", "tenant", "description"]
58
56
  extra_kwargs = {"namespace": {"default": get_default_namespace}}
59
57
 
60
58
 
@@ -64,16 +62,16 @@ class VRFDeviceAssignmentSerializer(ValidatedModelSerializer):
64
62
  fields = "__all__"
65
63
  validators = []
66
64
 
67
- def validate(self, data):
68
- if data.get("device"):
65
+ def validate(self, attrs):
66
+ if attrs.get("device"):
69
67
  validator = UniqueTogetherValidator(queryset=VRFDeviceAssignment.objects.all(), fields=("device", "vrf"))
70
- validator(data, self)
71
- if data.get("virtual_machine"):
68
+ validator(attrs, self)
69
+ if attrs.get("virtual_machine"):
72
70
  validator = UniqueTogetherValidator(
73
71
  queryset=VRFDeviceAssignment.objects.all(), fields=("virtual_machine", "vrf")
74
72
  )
75
- validator(data, self)
76
- return super().validate(data)
73
+ validator(attrs, self)
74
+ return super().validate(attrs)
77
75
 
78
76
 
79
77
  class VRFPrefixAssignmentSerializer(ValidatedModelSerializer):
@@ -91,7 +89,6 @@ class RouteTargetSerializer(NautobotModelSerializer, TaggedModelSerializerMixin)
91
89
  class Meta:
92
90
  model = RouteTarget
93
91
  fields = "__all__"
94
- list_display_fields = ["name", "tenant", "description"]
95
92
 
96
93
 
97
94
  #
@@ -105,12 +102,6 @@ class RIRSerializer(NautobotModelSerializer):
105
102
  class Meta:
106
103
  model = RIR
107
104
  fields = "__all__"
108
- list_display_fields = [
109
- "name",
110
- "is_private",
111
- "assigned_prefix_count",
112
- "description",
113
- ]
114
105
 
115
106
 
116
107
  #
@@ -124,7 +115,6 @@ class VLANGroupSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
124
115
  class Meta:
125
116
  model = VLANGroup
126
117
  fields = "__all__"
127
- list_display_fields = ["name", "location", "vlan_count", "description"]
128
118
 
129
119
 
130
120
  class VLANSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
@@ -139,34 +129,21 @@ class VLANSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
139
129
 
140
130
  class Meta:
141
131
  model = VLAN
142
- # TODO(jathan): These were taken from VLANDetailTable and not VLANTable. Let's make sure
143
- # these are correct.
144
132
  fields = "__all__"
145
- list_display_fields = [
146
- "vid",
147
- "locations",
148
- "vlan_group",
149
- "name",
150
- "prefixes",
151
- "tenant",
152
- "status",
153
- "role",
154
- "description",
155
- ]
156
133
  validators = []
157
134
  extra_kwargs = {"locations": {"read_only": True}}
158
135
 
159
- def validate(self, data):
136
+ def validate(self, attrs):
160
137
  # Validate uniqueness of vid and name if a group has been assigned.
161
- if data.get("vlan_group", None):
138
+ if attrs.get("vlan_group", None):
162
139
  for field in ["vid", "name"]:
163
140
  validator = UniqueTogetherValidator(queryset=VLAN.objects.all(), fields=("vlan_group", field))
164
- validator(data, self)
141
+ validator(attrs, self)
165
142
 
166
143
  # Enforce model validation
167
- super().validate(data)
144
+ super().validate(attrs)
168
145
 
169
- return data
146
+ return attrs
170
147
 
171
148
 
172
149
  class VLANLegacySerializer(VLANSerializer):
@@ -228,52 +205,21 @@ class PrefixSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
228
205
  write_only=True,
229
206
  )
230
207
 
208
+ def get_field_names(self, declared_fields, info):
209
+ """Add reverse M2M for VRF's to the fields for this serializer."""
210
+ field_names = list(super().get_field_names(declared_fields, info))
211
+ self.extend_field_names(field_names, "vrfs")
212
+ return field_names
213
+
231
214
  class Meta:
232
215
  model = Prefix
233
216
  fields = "__all__"
234
- list_display_fields = [
235
- "prefix",
236
- "namespace",
237
- "type",
238
- "status",
239
- "vrf",
240
- "tenant",
241
- "locations",
242
- "vlan",
243
- "role",
244
- "description",
245
- ]
246
217
  extra_kwargs = {
247
218
  "ip_version": {"read_only": True},
248
219
  "namespace": {"default": get_default_namespace},
249
220
  "prefix_length": {"read_only": True},
250
221
  "locations": {"read_only": True},
251
- }
252
-
253
- detail_view_config = {
254
- "layout": [
255
- {
256
- "Prefix": {
257
- "fields": [
258
- "prefix",
259
- "parent",
260
- "namespace",
261
- "type",
262
- "network",
263
- "broadcast",
264
- "prefix_length",
265
- "ip_version",
266
- "description",
267
- "role",
268
- "vlan",
269
- "locations",
270
- "tenant",
271
- "rir",
272
- "date_allocated",
273
- ]
274
- },
275
- },
276
- ],
222
+ "vrfs": {"read_only": True},
277
223
  }
278
224
 
279
225
 
@@ -374,16 +320,6 @@ class IPAddressSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
374
320
  class Meta:
375
321
  model = IPAddress
376
322
  fields = "__all__"
377
- list_display_fields = [
378
- "address",
379
- "type",
380
- "vrf",
381
- "status",
382
- "role",
383
- "tenant",
384
- "dns_name",
385
- "description",
386
- ]
387
323
  extra_kwargs = {
388
324
  "ip_version": {"read_only": True},
389
325
  "mask_length": {"read_only": True},
@@ -391,42 +327,16 @@ class IPAddressSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
391
327
  "parent": {"required": False},
392
328
  }
393
329
 
394
- detail_view_config = {
395
- "layout": [
396
- {
397
- "IP Address": {
398
- "fields": [
399
- # FixMe(timizuo): Missing in new-ui; resolve when working on #4355
400
- "namespace",
401
- "ip_version",
402
- "type",
403
- "role",
404
- "dns_name",
405
- "description",
406
- ]
407
- },
408
- "Operational Details": {
409
- "fields": [
410
- "tenant",
411
- "assigned", # FixMe(timizuo) Missing in new-ui; resolve when working on #4355
412
- "nat_inside",
413
- "nat_outside_list",
414
- ]
415
- },
416
- },
417
- ],
418
- }
419
-
420
- def validate(self, data):
421
- namespace = data.get("namespace", None)
422
- parent = data.get("parent", None)
330
+ def validate(self, attrs):
331
+ namespace = attrs.get("namespace", None)
332
+ parent = attrs.get("parent", None)
423
333
 
424
334
  # Only assert namespace/parent on create.
425
335
  if self.instance is None and not any([namespace, parent]):
426
336
  raise ValidationError({"__all__": "One of parent or namespace must be provided"})
427
337
 
428
- super().validate(data)
429
- return data
338
+ super().validate(attrs)
339
+ return attrs
430
340
 
431
341
  def get_field_names(self, declared_fields, info):
432
342
  """Add reverse relations to the automatically discovered fields."""
@@ -476,9 +386,9 @@ class IPAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMixin
476
386
  "custom_fields",
477
387
  )
478
388
 
479
- def validate(self, data):
480
- data["mask_length"] = self.context["prefix"].prefix_length
481
- return super().validate(data)
389
+ def validate(self, attrs):
390
+ attrs["mask_length"] = self.context["prefix"].prefix_length
391
+ return super().validate(attrs)
482
392
 
483
393
 
484
394
  class VLANAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
@@ -488,11 +398,13 @@ class VLANAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMix
488
398
 
489
399
  vid = serializers.IntegerField(required=False, min_value=constants.VLAN_VID_MIN, max_value=constants.VLAN_VID_MAX)
490
400
 
491
- def validate(self, data):
492
- """Skip `ValidatedModel` validation.
401
+ def validate(self, attrs):
402
+ """
403
+ Skip `ValidatedModel` validation.
404
+
493
405
  This allows to skip `vid` attribute of `VLAN` model, while validate name and status.
494
406
  """
495
- return data
407
+ return attrs
496
408
 
497
409
  class Meta(VLANSerializer.Meta):
498
410
  model = VLAN
@@ -521,19 +433,19 @@ class IPAddressToInterfaceSerializer(ValidatedModelSerializer):
521
433
  fields = "__all__"
522
434
  validators = []
523
435
 
524
- def validate(self, data):
436
+ def validate(self, attrs):
525
437
  # Validate uniqueness of (parent, name) since we omitted the automatically created validator from Meta.
526
- if data.get("interface"):
438
+ if attrs.get("interface"):
527
439
  validator = UniqueTogetherValidator(
528
440
  queryset=IPAddressToInterface.objects.all(), fields=("interface", "ip_address")
529
441
  )
530
- validator(data, self)
531
- if data.get("vm_interface"):
442
+ validator(attrs, self)
443
+ if attrs.get("vm_interface"):
532
444
  validator = UniqueTogetherValidator(
533
445
  queryset=IPAddressToInterface.objects.all(), fields=("vm_interface", "ip_address")
534
446
  )
535
- validator(data, self)
536
- return super().validate(data)
447
+ validator(attrs, self)
448
+ return super().validate(attrs)
537
449
 
538
450
 
539
451
  #
@@ -559,17 +471,12 @@ class ServiceSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
559
471
  "device": {"help_text": "Required if no virtual_machine is specified"},
560
472
  "virtual_machine": {"help_text": "Required if no device is specified"},
561
473
  }
562
- # TODO(jathan): We need to account for the "parent" field from the `ServiceTable` which is
563
- # an either/or column for `device` or `virtual_machine`. For now it's hard-coded to
564
- # `device`.
565
- # list_display_fields = ["name", "parent", "protocol", "ports", "description"]
566
- list_display_fields = ["name", "device", "protocol", "ports", "description"]
567
-
568
- def validate(self, data):
569
- if data.get("device"):
474
+
475
+ def validate(self, attrs):
476
+ if attrs.get("device"):
570
477
  validator = UniqueTogetherValidator(queryset=Service.objects.all(), fields=("name", "device"))
571
- validator(data, self)
572
- if data.get("virtual_machine"):
478
+ validator(attrs, self)
479
+ if attrs.get("virtual_machine"):
573
480
  validator = UniqueTogetherValidator(queryset=Service.objects.all(), fields=("name", "virtual_machine"))
574
- validator(data, self)
575
- return super().validate(data)
481
+ validator(attrs, self)
482
+ return super().validate(attrs)
@@ -9,6 +9,7 @@ from rest_framework.response import Response
9
9
  from rest_framework.serializers import IntegerField, ListSerializer
10
10
 
11
11
  from nautobot.core.api.authentication import TokenPermissions
12
+ from nautobot.core.constants import MAX_PAGE_SIZE_DEFAULT, PAGINATE_COUNT_DEFAULT
12
13
  from nautobot.core.models.querysets import count_related
13
14
  from nautobot.core.utils.config import get_settings_or_config
14
15
  from nautobot.dcim.models import Location
@@ -49,21 +50,19 @@ class NamespaceViewSet(NautobotModelViewSet):
49
50
 
50
51
 
51
52
  class VRFViewSet(NautobotModelViewSet):
52
- queryset = VRF.objects.select_related("namespace", "tenant").prefetch_related(
53
- "devices", "virtual_machines", "prefixes", "import_targets", "export_targets", "tags"
54
- )
53
+ queryset = VRF.objects.all()
55
54
  serializer_class = serializers.VRFSerializer
56
55
  filterset_class = filters.VRFFilterSet
57
56
 
58
57
 
59
58
  class VRFDeviceAssignmentViewSet(NautobotModelViewSet):
60
- queryset = VRFDeviceAssignment.objects.select_related("vrf", "device", "virtual_machine")
59
+ queryset = VRFDeviceAssignment.objects.all()
61
60
  serializer_class = serializers.VRFDeviceAssignmentSerializer
62
61
  filterset_class = filters.VRFDeviceAssignmentFilterSet
63
62
 
64
63
 
65
64
  class VRFPrefixAssignmentViewSet(NautobotModelViewSet):
66
- queryset = VRFPrefixAssignment.objects.select_related("vrf", "prefix")
65
+ queryset = VRFPrefixAssignment.objects.all()
67
66
  serializer_class = serializers.VRFPrefixAssignmentSerializer
68
67
  filterset_class = filters.VRFPrefixAssignmentFilterSet
69
68
 
@@ -74,7 +73,7 @@ class VRFPrefixAssignmentViewSet(NautobotModelViewSet):
74
73
 
75
74
 
76
75
  class RouteTargetViewSet(NautobotModelViewSet):
77
- queryset = RouteTarget.objects.select_related("tenant").prefetch_related("tags")
76
+ queryset = RouteTarget.objects.all()
78
77
  serializer_class = serializers.RouteTargetSerializer
79
78
  filterset_class = filters.RouteTargetFilterSet
80
79
 
@@ -109,21 +108,14 @@ class RIRViewSet(NautobotModelViewSet):
109
108
  update=extend_schema(responses={"200": serializers.PrefixLegacySerializer}, versions=["2.0", "2.1"]),
110
109
  )
111
110
  class PrefixViewSet(NautobotModelViewSet):
112
- queryset = Prefix.objects.select_related(
113
- "namespace",
114
- "parent",
115
- "rir",
116
- "role",
117
- "status",
118
- "tenant",
119
- "vlan",
120
- ).prefetch_related("locations", "tags")
111
+ queryset = Prefix.objects.all()
121
112
  serializer_class = serializers.PrefixSerializer
122
113
  filterset_class = filters.PrefixFilterSet
123
114
 
124
115
  def get_serializer_class(self):
125
116
  if (
126
117
  not getattr(self, "swagger_fake_view", False)
118
+ and hasattr(self.request, "major_version")
127
119
  and self.request.major_version == 2
128
120
  and self.request.minor_version < 2
129
121
  ):
@@ -139,15 +131,15 @@ class PrefixViewSet(NautobotModelViewSet):
139
131
  )
140
132
  default_code = "precondition_failed"
141
133
 
142
- def retrieve(self, request, pk=None):
134
+ def retrieve(self, request, *args, pk=None, **kwargs):
143
135
  try:
144
- return super().retrieve(request, pk)
136
+ return super().retrieve(request, *args, pk=pk, **kwargs)
145
137
  except Location.MultipleObjectsReturned as e:
146
138
  raise self.LocationIncompatibleLegacyBehavior from e
147
139
 
148
- def list(self, request):
140
+ def list(self, request, *args, **kwargs):
149
141
  try:
150
- return super().list(request)
142
+ return super().list(request, *args, **kwargs)
151
143
  except Location.MultipleObjectsReturned as e:
152
144
  raise self.LocationIncompatibleLegacyBehavior from e
153
145
 
@@ -185,20 +177,15 @@ class PrefixViewSet(NautobotModelViewSet):
185
177
  available_prefixes = prefix.get_available_prefixes()
186
178
 
187
179
  # Validate Requested Prefixes' length
188
- serializer = serializers.PrefixLengthSerializer(
189
- data=request.data if isinstance(request.data, list) else [request.data],
190
- many=True,
191
- context={
192
- "request": request,
193
- "prefix": prefix,
194
- },
195
- )
196
- serializer.is_valid(raise_exception=True)
197
-
198
- requested_prefixes = serializer.validated_data
199
- # Allocate prefixes to the requested objects based on availability within the parent
180
+ requested_prefixes = request.data if isinstance(request.data, list) else [request.data]
200
181
  for requested_prefix in requested_prefixes:
201
- # Find the first available prefix equal to or larger than the requested size
182
+ # If the prefix_length is not an integer, return a 400 using the
183
+ # serializer.is_valid(raise_exception=True) method call below
184
+ if not isinstance(requested_prefix["prefix_length"], int):
185
+ return Response(
186
+ {"prefix_length": "This field must be an integer."},
187
+ status=status.HTTP_400_BAD_REQUEST,
188
+ )
202
189
  for available_prefix in available_prefixes.iter_cidrs():
203
190
  if requested_prefix["prefix_length"] >= available_prefix.prefixlen:
204
191
  allocated_prefix = f"{available_prefix.network}/{requested_prefix['prefix_length']}"
@@ -210,11 +197,6 @@ class PrefixViewSet(NautobotModelViewSet):
210
197
  {"detail": "Insufficient space is available to accommodate the requested prefix size(s)"},
211
198
  status=status.HTTP_204_NO_CONTENT,
212
199
  )
213
-
214
- # The serializer usage above has mapped "custom_fields" dict to "_custom_field_data".
215
- # We need to convert it back to "custom_fields" as we're going to deserialize it a second time below
216
- requested_prefix["custom_fields"] = requested_prefix.pop("_custom_field_data", {})
217
-
218
200
  # Remove the allocated prefix from the list of available prefixes
219
201
  available_prefixes.remove(allocated_prefix)
220
202
 
@@ -275,17 +257,7 @@ class PrefixViewSet(NautobotModelViewSet):
275
257
  "nautobot.ipam.api.views.available_ips", blocking_timeout=5, timeout=settings.REDIS_LOCK_TIMEOUT
276
258
  ):
277
259
  # Normalize to a list of objects
278
- serializer = serializers.IPAllocationSerializer(
279
- data=request.data if isinstance(request.data, list) else [request.data],
280
- many=True,
281
- context={
282
- "request": request,
283
- "prefix": prefix,
284
- },
285
- )
286
- serializer.is_valid(raise_exception=True)
287
-
288
- requested_ips = serializer.validated_data
260
+ requested_ips = request.data if isinstance(request.data, list) else [request.data]
289
261
 
290
262
  # Determine if the requested number of IPs is available
291
263
  available_ips = prefix.get_available_ips()
@@ -306,9 +278,6 @@ class PrefixViewSet(NautobotModelViewSet):
306
278
  for requested_ip in requested_ips:
307
279
  requested_ip["address"] = f"{next(available_ips)}/{prefix_length}"
308
280
  requested_ip["namespace"] = prefix.namespace
309
- # The serializer usage above has mapped "custom_fields" dict to "_custom_field_data".
310
- # We need to convert it back to "custom_fields" as we're going to deserialize it a second time below
311
- requested_ip["custom_fields"] = requested_ip.pop("_custom_field_data", {})
312
281
 
313
282
  # Initialize the serializer with a list or a single object depending on what was requested
314
283
  context = {"request": request, "depth": 0}
@@ -326,11 +295,15 @@ class PrefixViewSet(NautobotModelViewSet):
326
295
  # Determine the maximum number of IPs to return
327
296
  else:
328
297
  try:
329
- limit = int(request.query_params.get("limit", get_settings_or_config("PAGINATE_COUNT")))
298
+ limit = int(
299
+ request.query_params.get(
300
+ "limit", get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
301
+ )
302
+ )
330
303
  except ValueError:
331
- limit = get_settings_or_config("PAGINATE_COUNT")
332
- if get_settings_or_config("MAX_PAGE_SIZE"):
333
- limit = min(limit, get_settings_or_config("MAX_PAGE_SIZE"))
304
+ limit = get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
305
+ if get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT):
306
+ limit = min(limit, get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT))
334
307
 
335
308
  # Calculate available IPs within the prefix
336
309
  ip_list = []
@@ -351,7 +324,7 @@ class PrefixViewSet(NautobotModelViewSet):
351
324
 
352
325
 
353
326
  class PrefixLocationAssignmentViewSet(NautobotModelViewSet):
354
- queryset = PrefixLocationAssignment.objects.select_related("prefix", "location")
327
+ queryset = PrefixLocationAssignment.objects.all()
355
328
  serializer_class = serializers.PrefixLocationAssignmentSerializer
356
329
  filterset_class = filters.PrefixLocationAssignmentFilterSet
357
330
 
@@ -362,13 +335,7 @@ class PrefixLocationAssignmentViewSet(NautobotModelViewSet):
362
335
 
363
336
 
364
337
  class IPAddressViewSet(NautobotModelViewSet):
365
- queryset = IPAddress.objects.select_related(
366
- "nat_inside",
367
- "parent",
368
- "role",
369
- "status",
370
- "tenant",
371
- ).prefetch_related("tags", "nat_outside_list")
338
+ queryset = IPAddress.objects.select_related("parent__namespace")
372
339
  serializer_class = serializers.IPAddressSerializer
373
340
  filterset_class = filters.IPAddressFilterSet
374
341
 
@@ -379,7 +346,7 @@ class IPAddressViewSet(NautobotModelViewSet):
379
346
 
380
347
 
381
348
  class IPAddressToInterfaceViewSet(NautobotModelViewSet):
382
- queryset = IPAddressToInterface.objects.select_related("interface", "ip_address", "vm_interface")
349
+ queryset = IPAddressToInterface.objects.all()
383
350
  serializer_class = serializers.IPAddressToInterfaceSerializer
384
351
  filterset_class = filters.IPAddressToInterfaceFilterSet
385
352
 
@@ -390,11 +357,7 @@ class IPAddressToInterfaceViewSet(NautobotModelViewSet):
390
357
 
391
358
 
392
359
  class VLANGroupViewSet(NautobotModelViewSet):
393
- queryset = (
394
- VLANGroup.objects.select_related("location")
395
- .prefetch_related("tags")
396
- .annotate(vlan_count=count_related(VLAN, "vlan_group"))
397
- )
360
+ queryset = VLANGroup.objects.annotate(vlan_count=count_related(VLAN, "vlan_group"))
398
361
  serializer_class = serializers.VLANGroupSerializer
399
362
  filterset_class = filters.VLANGroupFilterSet
400
363
 
@@ -442,16 +405,7 @@ class VLANGroupViewSet(NautobotModelViewSet):
442
405
  "nautobot.ipam.api.views.available_vlans", blocking_timeout=5, timeout=settings.REDIS_LOCK_TIMEOUT
443
406
  ):
444
407
  # Normalize to a list of objects
445
- serializer = serializers.VLANAllocationSerializer(
446
- data=request.data if isinstance(request.data, list) else [request.data],
447
- many=True,
448
- context={
449
- "request": request,
450
- "vlan_group": vlan_group,
451
- },
452
- )
453
- serializer.is_valid(raise_exception=True)
454
- requested_vlans = serializer.validated_data
408
+ requested_vlans = request.data if isinstance(request.data, list) else [request.data]
455
409
 
456
410
  # Determine if the requested number of VLANs is available
457
411
  available_vids = vlan_group.available_vids
@@ -487,20 +441,28 @@ class VLANGroupViewSet(NautobotModelViewSet):
487
441
  requested_vlan["vid"] = next(_available_vids)
488
442
 
489
443
  # Check requested `vlan_group`
490
- if "vlan_group" in requested_vlan and requested_vlan["vlan_group"] != vlan_group:
491
- return Response(
492
- {
493
- "detail": f"Invalid VLAN Group requested: {requested_vlan['vlan_group']}. "
494
- f"Only VLAN Group {vlan_group} is permitted."
495
- },
496
- status=status.HTTP_204_NO_CONTENT,
497
- )
444
+ if "vlan_group" in requested_vlan:
445
+ requested_vlan_group = None
446
+ requested_vlan_group_pk = requested_vlan["vlan_group"]
447
+ try:
448
+ requested_vlan_group = VLANGroup.objects.get(pk=requested_vlan_group_pk)
449
+ except VLANGroup.DoesNotExist:
450
+ return Response(
451
+ {"detail": f"VLAN Group with pk {requested_vlan_group_pk} does not exist."},
452
+ status=status.HTTP_204_NO_CONTENT,
453
+ )
454
+
455
+ if requested_vlan_group != vlan_group:
456
+ return Response(
457
+ {
458
+ "detail": f"Invalid VLAN Group requested: {requested_vlan_group}. "
459
+ f"Only VLAN Group {vlan_group} is permitted."
460
+ },
461
+ status=status.HTTP_204_NO_CONTENT,
462
+ )
498
463
  else:
499
464
  requested_vlan["vlan_group"] = vlan_group.pk
500
465
 
501
- # Rewrite custom field data
502
- requested_vlan["custom_fields"] = requested_vlan.pop("_custom_field_data", {})
503
-
504
466
  # Initialize the serializer with a list or a single object depending on what was requested
505
467
  context = {"request": request, "depth": 0}
506
468
 
@@ -527,12 +489,16 @@ class VLANGroupViewSet(NautobotModelViewSet):
527
489
 
528
490
  else:
529
491
  try:
530
- limit = int(request.query_params.get("limit", get_settings_or_config("PAGINATE_COUNT")))
492
+ limit = int(
493
+ request.query_params.get(
494
+ "limit", get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
495
+ )
496
+ )
531
497
  except ValueError:
532
- limit = get_settings_or_config("PAGINATE_COUNT")
498
+ limit = get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
533
499
 
534
- if get_settings_or_config("MAX_PAGE_SIZE"):
535
- limit = min(limit, get_settings_or_config("MAX_PAGE_SIZE"))
500
+ if get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT):
501
+ limit = min(limit, get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT))
536
502
 
537
503
  if isinstance(limit, int) and limit >= 0:
538
504
  vids = vlan_group.available_vids[0:limit]
@@ -573,16 +539,7 @@ class VLANGroupViewSet(NautobotModelViewSet):
573
539
  update=extend_schema(responses={"200": serializers.VLANLegacySerializer}, versions=["2.0", "2.1"]),
574
540
  )
575
541
  class VLANViewSet(NautobotModelViewSet):
576
- queryset = (
577
- VLAN.objects.select_related(
578
- "vlan_group",
579
- "status",
580
- "role",
581
- "tenant",
582
- )
583
- .prefetch_related("tags")
584
- .annotate(prefix_count=count_related(Prefix, "vlan"))
585
- )
542
+ queryset = VLAN.objects.annotate(prefix_count=count_related(Prefix, "vlan"))
586
543
  serializer_class = serializers.VLANSerializer
587
544
  filterset_class = filters.VLANFilterSet
588
545
 
@@ -597,6 +554,7 @@ class VLANViewSet(NautobotModelViewSet):
597
554
  def get_serializer_class(self):
598
555
  if (
599
556
  not getattr(self, "swagger_fake_view", False)
557
+ and hasattr(self.request, "major_version")
600
558
  and self.request.major_version == 2
601
559
  and self.request.minor_version < 2
602
560
  ):
@@ -604,15 +562,15 @@ class VLANViewSet(NautobotModelViewSet):
604
562
  return serializers.VLANLegacySerializer
605
563
  return super().get_serializer_class()
606
564
 
607
- def retrieve(self, request, pk=None):
565
+ def retrieve(self, request, *args, pk=None, **kwargs):
608
566
  try:
609
- return super().retrieve(request, pk)
567
+ return super().retrieve(request, *args, pk=pk, **kwargs)
610
568
  except Location.MultipleObjectsReturned as e:
611
569
  raise self.LocationIncompatibleLegacyBehavior from e
612
570
 
613
- def list(self, request):
571
+ def list(self, request, *args, **kwargs):
614
572
  try:
615
- return super().list(request)
573
+ return super().list(request, *args, **kwargs)
616
574
  except Location.MultipleObjectsReturned as e:
617
575
  raise self.LocationIncompatibleLegacyBehavior from e
618
576
 
@@ -624,7 +582,7 @@ class VLANViewSet(NautobotModelViewSet):
624
582
 
625
583
 
626
584
  class VLANLocationAssignmentViewSet(NautobotModelViewSet):
627
- queryset = VLANLocationAssignment.objects.select_related("vlan", "location")
585
+ queryset = VLANLocationAssignment.objects.all()
628
586
  serializer_class = serializers.VLANLocationAssignmentSerializer
629
587
  filterset_class = filters.VLANLocationAssignmentFilterSet
630
588
 
@@ -635,6 +593,6 @@ class VLANLocationAssignmentViewSet(NautobotModelViewSet):
635
593
 
636
594
 
637
595
  class ServiceViewSet(NautobotModelViewSet):
638
- queryset = Service.objects.select_related("device", "virtual_machine").prefetch_related("tags", "ip_addresses")
596
+ queryset = Service.objects.all()
639
597
  serializer_class = serializers.ServiceSerializer
640
598
  filterset_class = filters.ServiceFilterSet
nautobot/ipam/factory.py CHANGED
@@ -410,7 +410,7 @@ class PrefixFactory(PrimaryModelFactory):
410
410
  # Calculate prefix length for child prefixes to allow them to fit in the parent prefix without creating duplicate prefix
411
411
  child_cidr = self.prefix_length + max(1, math.ceil(math.log(child_count, 2)))
412
412
  # Raise exception for invalid cidr length (>128 for ipv6, >32 for ipv4)
413
- if child_cidr > 128 or self.ip_version == 4 and child_cidr > 32:
413
+ if child_cidr > 128 or (self.ip_version == 4 and child_cidr > 32):
414
414
  raise ValueError(f"Unable to create {child_count} child prefixes in container prefix {self.cidr_str}.")
415
415
 
416
416
  weights = [1, 6, 3] # prefer network and pool prefixes