nautobot 2.4.18__py3-none-any.whl → 2.4.19__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 (583) hide show
  1. nautobot/apps/ui.py +6 -0
  2. nautobot/circuits/tables.py +1 -1
  3. nautobot/circuits/templates/circuits/circuit_create.html +7 -7
  4. nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -5
  5. nautobot/circuits/templates/circuits/circuittermination_create.html +26 -26
  6. nautobot/circuits/templates/circuits/inc/circuit_termination.html +20 -20
  7. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +3 -3
  8. nautobot/circuits/templates/circuits/inc/circuit_termination_speed_fragment.html +7 -7
  9. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +1 -3
  10. nautobot/circuits/views.py +26 -9
  11. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +1 -4
  12. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +1 -7
  13. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +1 -3
  14. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +1 -5
  15. nautobot/cloud/views.py +45 -0
  16. nautobot/core/graphql/generators.py +5 -2
  17. nautobot/core/jobs/bulk_actions.py +48 -85
  18. nautobot/core/models/querysets.py +2 -1
  19. nautobot/core/templates/40x.html +15 -15
  20. nautobot/core/templates/500.html +21 -21
  21. nautobot/core/templates/admin/app_index.html +8 -8
  22. nautobot/core/templates/admin/base.html +104 -104
  23. nautobot/core/templates/admin/change_form.html +65 -65
  24. nautobot/core/templates/admin/change_list.html +60 -60
  25. nautobot/core/templates/admin/change_list_results.html +39 -39
  26. nautobot/core/templates/admin/config/config.html +47 -47
  27. nautobot/core/templates/admin/delete_confirmation.html +47 -47
  28. nautobot/core/templates/admin/edit_inline/stacked.html +124 -124
  29. nautobot/core/templates/admin/edit_inline/tabular.html +60 -60
  30. nautobot/core/templates/admin/includes/fieldset.html +4 -4
  31. nautobot/core/templates/admin/index.html +60 -60
  32. nautobot/core/templates/admin/prepopulated_fields_js.html +18 -18
  33. nautobot/core/templates/admin/submit_line.html +4 -4
  34. nautobot/core/templates/base_django.html +46 -46
  35. nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +8 -8
  36. nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +8 -8
  37. nautobot/core/templates/buttons/export.html +3 -3
  38. nautobot/core/templates/components/breadcrumbs.html +5 -5
  39. nautobot/core/templates/components/button/default.html +3 -3
  40. nautobot/core/templates/components/button/dropdown.html +7 -7
  41. nautobot/core/templates/components/button/formbutton.html +4 -4
  42. nautobot/core/templates/components/panel/body_content_data_table.html +1 -1
  43. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +3 -0
  44. nautobot/core/templates/components/panel/footer_content_table.html +3 -1
  45. nautobot/core/templates/components/panel/header_extra_content_table.html +10 -1
  46. nautobot/core/templates/components/tab/content_wrapper.html +1 -1
  47. nautobot/core/templates/components/tab/label_wrapper.html +1 -1
  48. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +10 -3
  49. nautobot/core/templates/generic/object_bulk_add_component.html +40 -40
  50. nautobot/core/templates/generic/object_bulk_create.html +3 -3
  51. nautobot/core/templates/generic/object_bulk_destroy.html +6 -6
  52. nautobot/core/templates/generic/object_bulk_update.html +52 -52
  53. nautobot/core/templates/generic/object_import.html +33 -33
  54. nautobot/core/templates/generic/object_list.html +267 -267
  55. nautobot/core/templates/generic/object_retrieve.html +261 -261
  56. nautobot/core/templates/graphene/graphiql.html +127 -127
  57. nautobot/core/templates/home.html +62 -62
  58. nautobot/core/templates/inc/computed_fields/panel_data.html +13 -13
  59. nautobot/core/templates/inc/created_updated.html +8 -8
  60. nautobot/core/templates/inc/custom_fields/panel_data.html +13 -13
  61. nautobot/core/templates/inc/dynamic_groups_panel.html +11 -11
  62. nautobot/core/templates/inc/footer.html +19 -19
  63. nautobot/core/templates/inc/javascript.html +1 -1
  64. nautobot/core/templates/inc/media.html +46 -46
  65. nautobot/core/templates/inc/nav_menu.html +1 -1
  66. nautobot/core/templates/inc/relationships_table_rows.html +22 -22
  67. nautobot/core/templates/inc/tenant_table_row.html +1 -1
  68. nautobot/core/templates/login.html +77 -77
  69. nautobot/core/templates/media_failure.html +38 -38
  70. nautobot/core/templates/panel_table.html +1 -1
  71. nautobot/core/templates/rest_framework/api.html +3 -3
  72. nautobot/core/templates/search.html +1 -1
  73. nautobot/core/templates/swagger_ui.html +9 -9
  74. nautobot/core/templates/utilities/confirmation_form.html +18 -18
  75. nautobot/core/templates/utilities/render_field.html +1 -1
  76. nautobot/core/templates/utilities/render_jinja2.html +43 -43
  77. nautobot/core/templates/utilities/templatetags/filter_form_modal.html +56 -56
  78. nautobot/core/templates/utilities/templatetags/utilization_graph.html +1 -1
  79. nautobot/core/templates/utilities/theme_preview.html +799 -799
  80. nautobot/core/templates/utilities/worker_status.html +122 -122
  81. nautobot/core/templates/widgets/clearable_file.html +3 -3
  82. nautobot/core/templates/widgets/sluginput.html +1 -1
  83. nautobot/core/templatetags/buttons.py +8 -2
  84. nautobot/core/templatetags/helpers.py +1 -1
  85. nautobot/core/testing/integration.py +7 -4
  86. nautobot/core/testing/views.py +24 -5
  87. nautobot/core/tests/test_breadcrumbs.py +78 -4
  88. nautobot/core/tests/test_commands.py +7 -4
  89. nautobot/core/tests/test_graphql.py +20 -5
  90. nautobot/core/tests/test_jobs.py +34 -21
  91. nautobot/core/tests/test_ui.py +175 -1
  92. nautobot/core/tests/test_utils.py +35 -0
  93. nautobot/core/tests/test_views_generic.py +43 -0
  94. nautobot/core/tests/test_views_utils.py +239 -5
  95. nautobot/core/ui/breadcrumbs.py +208 -21
  96. nautobot/core/ui/bulk_buttons.py +8 -0
  97. nautobot/core/ui/object_detail.py +138 -55
  98. nautobot/core/ui/titles.py +1 -0
  99. nautobot/core/utils/requests.py +27 -2
  100. nautobot/core/views/generic.py +41 -31
  101. nautobot/core/views/mixins.py +80 -110
  102. nautobot/core/views/utils.py +153 -1
  103. nautobot/dcim/api/serializers.py +8 -2
  104. nautobot/dcim/constants.py +1 -0
  105. nautobot/dcim/factory.py +4 -3
  106. nautobot/dcim/filters/mixins.py +1 -2
  107. nautobot/dcim/forms.py +5 -1
  108. nautobot/dcim/migrations/0074_alter_rack_u_height.py +21 -0
  109. nautobot/dcim/models/devices.py +26 -1
  110. nautobot/dcim/models/racks.py +2 -2
  111. nautobot/dcim/templates/dcim/cable.html +53 -53
  112. nautobot/dcim/templates/dcim/cable_connect.html +182 -182
  113. nautobot/dcim/templates/dcim/cable_trace.html +1 -1
  114. nautobot/dcim/templates/dcim/console_port_connection_list.html +5 -5
  115. nautobot/dcim/templates/dcim/consoleport.html +86 -86
  116. nautobot/dcim/templates/dcim/consoleserverport.html +86 -86
  117. nautobot/dcim/templates/dcim/controller_create.html +34 -34
  118. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -68
  119. nautobot/dcim/templates/dcim/device/base.html +1 -104
  120. nautobot/dcim/templates/dcim/device/config.html +17 -17
  121. nautobot/dcim/templates/dcim/device/consoleports.html +1 -52
  122. nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -52
  123. nautobot/dcim/templates/dcim/device/devicebays.html +1 -48
  124. nautobot/dcim/templates/dcim/device/frontports.html +1 -52
  125. nautobot/dcim/templates/dcim/device/interfaces.html +1 -56
  126. nautobot/dcim/templates/dcim/device/inventory.html +1 -48
  127. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +64 -64
  128. nautobot/dcim/templates/dcim/device/modulebays.html +1 -48
  129. nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -52
  130. nautobot/dcim/templates/dcim/device/powerports.html +1 -52
  131. nautobot/dcim/templates/dcim/device/rearports.html +1 -52
  132. nautobot/dcim/templates/dcim/device/status.html +66 -66
  133. nautobot/dcim/templates/dcim/device/wireless.html +1 -72
  134. nautobot/dcim/templates/dcim/device.html +4 -422
  135. nautobot/dcim/templates/dcim/device_component_add.html +25 -25
  136. nautobot/dcim/templates/dcim/device_create.html +229 -0
  137. nautobot/dcim/templates/dcim/device_edit.html +2 -227
  138. nautobot/dcim/templates/dcim/devicebay.html +41 -41
  139. nautobot/dcim/templates/dcim/devicebay_populate.html +32 -32
  140. nautobot/dcim/templates/dcim/devicetype_component_add.html +28 -28
  141. nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -3
  142. nautobot/dcim/templates/dcim/frontport.html +84 -84
  143. nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
  144. nautobot/dcim/templates/dcim/inc/device_interface_filter.html +8 -0
  145. nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +1 -15
  146. nautobot/dcim/templates/dcim/inc/location_hierarchy.html +22 -22
  147. nautobot/dcim/templates/dcim/interface.html +206 -206
  148. nautobot/dcim/templates/dcim/interface_connection_list.html +5 -5
  149. nautobot/dcim/templates/dcim/interfaceredundancygroupassociation_create.html +6 -6
  150. nautobot/dcim/templates/dcim/inventoryitem.html +44 -44
  151. nautobot/dcim/templates/dcim/inventoryitem_add.html +32 -32
  152. nautobot/dcim/templates/dcim/inventoryitem_edit.html +22 -22
  153. nautobot/dcim/templates/dcim/location_migrate_data_to_contact.html +46 -46
  154. nautobot/dcim/templates/dcim/location_retrieve.html +1 -7
  155. nautobot/dcim/templates/dcim/locationtype.html +1 -6
  156. nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -7
  157. nautobot/dcim/templates/dcim/module/base.html +85 -85
  158. nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
  159. nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
  160. nautobot/dcim/templates/dcim/module_retrieve.html +52 -52
  161. nautobot/dcim/templates/dcim/module_update.html +61 -61
  162. nautobot/dcim/templates/dcim/modulebay_destroy.html +1 -1
  163. nautobot/dcim/templates/dcim/modulebay_retrieve.html +85 -85
  164. nautobot/dcim/templates/dcim/modulebay_update.html +33 -33
  165. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  166. nautobot/dcim/templates/dcim/moduletype_retrieve.html +140 -144
  167. nautobot/dcim/templates/dcim/platform_create.html +38 -38
  168. nautobot/dcim/templates/dcim/power_port_connection_list.html +5 -5
  169. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -8
  170. nautobot/dcim/templates/dcim/poweroutlet.html +85 -85
  171. nautobot/dcim/templates/dcim/powerpanel_retrieve.html +1 -8
  172. nautobot/dcim/templates/dcim/powerport.html +91 -91
  173. nautobot/dcim/templates/dcim/rack_elevation_list.html +18 -18
  174. nautobot/dcim/templates/dcim/rack_retrieve.html +264 -274
  175. nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -3
  176. nautobot/dcim/templates/dcim/rearport.html +78 -78
  177. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -5
  178. nautobot/dcim/tests/integration/test_device_bulk_operations.py +3 -2
  179. nautobot/dcim/tests/integration/test_location_bulk_operations.py +6 -2
  180. nautobot/dcim/tests/test_api.py +33 -1
  181. nautobot/dcim/tests/test_views.py +148 -4
  182. nautobot/dcim/ui.py +29 -0
  183. nautobot/dcim/urls.py +1 -109
  184. nautobot/dcim/utils.py +30 -0
  185. nautobot/dcim/views.py +1009 -531
  186. nautobot/extras/tables.py +20 -0
  187. nautobot/extras/templates/extras/computedfield_edit.html +4 -4
  188. nautobot/extras/templates/extras/configcontext_update.html +1 -1
  189. nautobot/extras/templates/extras/configcontextschema_retrieve.html +32 -32
  190. nautobot/extras/templates/extras/customfield_update.html +23 -23
  191. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +38 -38
  192. nautobot/extras/templates/extras/dynamicgroup_update.html +62 -62
  193. nautobot/extras/templates/extras/gitrepository_list.html +10 -10
  194. nautobot/extras/templates/extras/gitrepository_retrieve.html +68 -68
  195. nautobot/extras/templates/extras/graphqlquery_retrieve.html +73 -73
  196. nautobot/extras/templates/extras/inc/configcontext_format.html +2 -2
  197. nautobot/extras/templates/extras/inc/job_table.html +10 -10
  198. nautobot/extras/templates/extras/inc/jobresult.html +21 -21
  199. nautobot/extras/templates/extras/inc/jobresult_js.html +6 -6
  200. nautobot/extras/templates/extras/inc/tags_panel.html +10 -10
  201. nautobot/extras/templates/extras/job.html +64 -64
  202. nautobot/extras/templates/extras/job_approval_request.html +9 -9
  203. nautobot/extras/templates/extras/job_bulk_edit.html +13 -13
  204. nautobot/extras/templates/extras/job_edit.html +45 -45
  205. nautobot/extras/templates/extras/job_list.html +4 -4
  206. nautobot/extras/templates/extras/jobresult_retrieve.html +0 -25
  207. nautobot/extras/templates/extras/marketplace.html +101 -101
  208. nautobot/extras/templates/extras/metadatatype_create.html +20 -20
  209. nautobot/extras/templates/extras/object_assign_contact_or_team.html +18 -18
  210. nautobot/extras/templates/extras/object_configcontext.html +1 -3
  211. nautobot/extras/templates/extras/objectchange.html +2 -165
  212. nautobot/extras/templates/extras/objectchange_retrieve.html +165 -0
  213. nautobot/extras/templates/extras/plugin_detail.html +41 -41
  214. nautobot/extras/templates/extras/plugins_list.html +9 -9
  215. nautobot/extras/templates/extras/plugins_tiles.html +26 -26
  216. nautobot/extras/templates/extras/relationship_edit.html +4 -4
  217. nautobot/extras/templates/extras/role_retrieve.html +13 -13
  218. nautobot/extras/templates/extras/scheduled_jobs_approval_queue_list.html +21 -21
  219. nautobot/extras/templates/extras/scheduledjob.html +128 -128
  220. nautobot/extras/templates/extras/secret_create.html +53 -53
  221. nautobot/extras/templates/extras/secretsgroup_update.html +13 -13
  222. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +3 -3
  223. nautobot/extras/templates/extras/webhook.html +79 -79
  224. nautobot/extras/tests/integration/test_relationships.py +6 -6
  225. nautobot/extras/tests/test_filters.py +1 -1
  226. nautobot/extras/tests/test_jobs.py +2 -0
  227. nautobot/extras/tests/test_views.py +3 -3
  228. nautobot/extras/urls.py +1 -3
  229. nautobot/extras/views.py +101 -27
  230. nautobot/ipam/filters.py +2 -2
  231. nautobot/ipam/migrations/0053_alter_vrfdeviceassignment_options_and_more.py +20 -0
  232. nautobot/ipam/models.py +34 -0
  233. nautobot/ipam/tables.py +3 -1
  234. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +4 -0
  235. nautobot/ipam/templates/ipam/inc/toggle_available.html +8 -8
  236. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +4 -4
  237. nautobot/ipam/templates/ipam/ipaddress.html +119 -123
  238. nautobot/ipam/templates/ipam/ipaddress_assign.html +10 -10
  239. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -1
  240. nautobot/ipam/templates/ipam/ipaddress_merge.html +180 -180
  241. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +48 -48
  242. nautobot/ipam/templates/ipam/prefix.html +2 -107
  243. nautobot/ipam/templates/ipam/prefix_create.html +34 -0
  244. nautobot/ipam/templates/ipam/prefix_edit.html +1 -34
  245. nautobot/ipam/templates/ipam/prefix_retrieve.html +3 -0
  246. nautobot/ipam/templates/ipam/service_retrieve.html +1 -6
  247. nautobot/ipam/templates/ipam/vlan_retrieve.html +1 -7
  248. nautobot/ipam/templates/ipam/vrf_edit.html +1 -1
  249. nautobot/ipam/tests/test_views.py +34 -0
  250. nautobot/ipam/ui.py +145 -0
  251. nautobot/ipam/urls.py +1 -46
  252. nautobot/ipam/utils/__init__.py +26 -0
  253. nautobot/ipam/views.py +219 -106
  254. nautobot/project-static/docs/404.html +11 -11
  255. nautobot/project-static/docs/apps/index.html +11 -11
  256. nautobot/project-static/docs/apps/nautobot-apps.html +11 -11
  257. nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js → bundle.f55a23d4.min.js} +2 -2
  258. nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js.map → bundle.f55a23d4.min.js.map} +2 -2
  259. nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css → main.e53b48f4.min.css} +1 -1
  260. nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css.map → main.e53b48f4.min.css.map} +1 -1
  261. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +11 -11
  262. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +11 -11
  263. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +11 -11
  264. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +11 -11
  265. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +11 -11
  266. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +11 -11
  267. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +11 -11
  268. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +11 -11
  269. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +11 -11
  270. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +11 -11
  271. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +11 -11
  272. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +11 -11
  273. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +11 -11
  274. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +11 -11
  275. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +11 -11
  276. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -11
  277. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +11 -11
  278. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +11 -11
  279. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -11
  280. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +11 -11
  281. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2174 -1226
  282. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +11 -11
  283. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +12 -12
  284. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +72 -27
  285. nautobot/project-static/docs/development/apps/api/configuration-view.html +11 -11
  286. nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -11
  287. nautobot/project-static/docs/development/apps/api/models/django-admin.html +11 -11
  288. nautobot/project-static/docs/development/apps/api/models/global-search.html +11 -11
  289. nautobot/project-static/docs/development/apps/api/models/graphql.html +11 -11
  290. nautobot/project-static/docs/development/apps/api/models/index.html +11 -11
  291. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +11 -11
  292. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +11 -11
  293. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +11 -11
  294. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +11 -11
  295. nautobot/project-static/docs/development/apps/api/platform-features/index.html +11 -11
  296. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -11
  297. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +11 -11
  298. nautobot/project-static/docs/development/apps/api/platform-features/prepopulating-data.html +11 -11
  299. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +11 -11
  300. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +11 -11
  301. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +11 -11
  302. nautobot/project-static/docs/development/apps/api/prometheus.html +11 -11
  303. nautobot/project-static/docs/development/apps/api/setup.html +11 -11
  304. nautobot/project-static/docs/development/apps/api/testing.html +11 -11
  305. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +11 -11
  306. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +11 -11
  307. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +11 -11
  308. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +11 -11
  309. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +11 -11
  310. nautobot/project-static/docs/development/apps/api/views/base-template.html +11 -11
  311. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +11 -11
  312. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +11 -11
  313. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +11 -11
  314. nautobot/project-static/docs/development/apps/api/views/index.html +11 -11
  315. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +11 -11
  316. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +11 -11
  317. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +11 -11
  318. nautobot/project-static/docs/development/apps/api/views/notes.html +11 -11
  319. nautobot/project-static/docs/development/apps/api/views/rest-api.html +11 -11
  320. nautobot/project-static/docs/development/apps/api/views/urls.html +11 -11
  321. nautobot/project-static/docs/development/apps/index.html +11 -11
  322. nautobot/project-static/docs/development/apps/migration/code-updates.html +11 -11
  323. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +11 -11
  324. nautobot/project-static/docs/development/apps/migration/from-v1.html +11 -11
  325. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +11 -11
  326. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +11 -11
  327. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +11 -11
  328. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +11 -11
  329. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +11 -11
  330. nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +11 -11
  331. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +11 -11
  332. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +11 -11
  333. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +11 -11
  334. nautobot/project-static/docs/development/apps/porting-from-netbox.html +11 -11
  335. nautobot/project-static/docs/development/core/application-registry.html +11 -11
  336. nautobot/project-static/docs/development/core/best-practices.html +11 -11
  337. nautobot/project-static/docs/development/core/bootstrap-ui.html +11 -11
  338. nautobot/project-static/docs/development/core/caching.html +11 -11
  339. nautobot/project-static/docs/development/core/controllers.html +11 -11
  340. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +11 -11
  341. nautobot/project-static/docs/development/core/generic-views.html +11 -11
  342. nautobot/project-static/docs/development/core/getting-started.html +50 -48
  343. nautobot/project-static/docs/development/core/homepage.html +11 -11
  344. nautobot/project-static/docs/development/core/index.html +11 -11
  345. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +11 -11
  346. nautobot/project-static/docs/development/core/model-checklist.html +11 -11
  347. nautobot/project-static/docs/development/core/model-features.html +11 -11
  348. nautobot/project-static/docs/development/core/natural-keys.html +11 -11
  349. nautobot/project-static/docs/development/core/navigation-menu.html +11 -11
  350. nautobot/project-static/docs/development/core/release-checklist.html +11 -11
  351. nautobot/project-static/docs/development/core/role-internals.html +11 -11
  352. nautobot/project-static/docs/development/core/settings.html +11 -11
  353. nautobot/project-static/docs/development/core/style-guide.html +15 -11
  354. nautobot/project-static/docs/development/core/templates.html +11 -11
  355. nautobot/project-static/docs/development/core/testing.html +11 -11
  356. nautobot/project-static/docs/development/core/ui-component-framework.html +11 -11
  357. nautobot/project-static/docs/development/core/user-preferences.html +11 -11
  358. nautobot/project-static/docs/development/index.html +11 -11
  359. nautobot/project-static/docs/development/jobs/getting-started.html +11 -11
  360. nautobot/project-static/docs/development/jobs/index.html +11 -11
  361. nautobot/project-static/docs/development/jobs/installation.html +11 -11
  362. nautobot/project-static/docs/development/jobs/job-extensions.html +11 -11
  363. nautobot/project-static/docs/development/jobs/job-logging.html +11 -11
  364. nautobot/project-static/docs/development/jobs/job-patterns.html +11 -11
  365. nautobot/project-static/docs/development/jobs/job-structure.html +11 -11
  366. nautobot/project-static/docs/development/jobs/migration/from-v1.html +11 -11
  367. nautobot/project-static/docs/development/jobs/testing.html +11 -11
  368. nautobot/project-static/docs/index.html +11 -11
  369. nautobot/project-static/docs/objects.inv +0 -0
  370. nautobot/project-static/docs/overview/application_stack.html +11 -11
  371. nautobot/project-static/docs/overview/design_philosophy.html +11 -11
  372. nautobot/project-static/docs/release-notes/index.html +11 -11
  373. nautobot/project-static/docs/release-notes/version-1.0.html +11 -11
  374. nautobot/project-static/docs/release-notes/version-1.1.html +11 -11
  375. nautobot/project-static/docs/release-notes/version-1.2.html +11 -11
  376. nautobot/project-static/docs/release-notes/version-1.3.html +11 -11
  377. nautobot/project-static/docs/release-notes/version-1.4.html +11 -11
  378. nautobot/project-static/docs/release-notes/version-1.5.html +11 -11
  379. nautobot/project-static/docs/release-notes/version-1.6.html +11 -11
  380. nautobot/project-static/docs/release-notes/version-2.0.html +11 -11
  381. nautobot/project-static/docs/release-notes/version-2.1.html +11 -11
  382. nautobot/project-static/docs/release-notes/version-2.2.html +11 -11
  383. nautobot/project-static/docs/release-notes/version-2.3.html +11 -11
  384. nautobot/project-static/docs/release-notes/version-2.4.html +196 -11
  385. nautobot/project-static/docs/search/search_index.json +1 -1
  386. nautobot/project-static/docs/sitemap.xml +300 -300
  387. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  388. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +11 -11
  389. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +11 -11
  390. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +11 -11
  391. nautobot/project-static/docs/user-guide/administration/configuration/index.html +11 -11
  392. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +11 -11
  393. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +11 -11
  394. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +11 -11
  395. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +89 -14
  396. nautobot/project-static/docs/user-guide/administration/guides/docker.html +11 -11
  397. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +11 -11
  398. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +11 -11
  399. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +11 -11
  400. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +11 -11
  401. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +11 -11
  402. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +11 -11
  403. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +11 -11
  404. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +11 -11
  405. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +11 -11
  406. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +11 -11
  407. nautobot/project-static/docs/user-guide/administration/installation/index.html +11 -11
  408. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +11 -11
  409. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +11 -11
  410. nautobot/project-static/docs/user-guide/administration/installation/services.html +11 -11
  411. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +11 -11
  412. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +11 -11
  413. nautobot/project-static/docs/user-guide/administration/security/index.html +11 -11
  414. nautobot/project-static/docs/user-guide/administration/security/notices.html +11 -11
  415. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +11 -11
  416. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +11 -11
  417. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +11 -11
  418. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +11 -11
  419. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +11 -11
  420. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +11 -11
  421. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +11 -11
  422. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +11 -11
  423. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +11 -11
  424. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +11 -11
  425. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +11 -11
  426. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +11 -11
  427. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +11 -11
  428. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +11 -11
  429. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +11 -11
  430. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +11 -11
  431. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +11 -11
  432. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +11 -11
  433. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +11 -11
  434. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +11 -11
  435. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +11 -11
  436. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +11 -11
  437. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +11 -11
  438. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +11 -11
  439. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +11 -11
  440. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +11 -11
  441. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +11 -11
  442. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +11 -11
  443. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -11
  444. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +11 -11
  445. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +11 -11
  446. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +11 -11
  447. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +11 -11
  448. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +11 -11
  449. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +11 -11
  450. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +11 -11
  451. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +11 -11
  452. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +11 -11
  453. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +11 -11
  454. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +11 -11
  455. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +11 -11
  456. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +11 -11
  457. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +11 -11
  458. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +11 -11
  459. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +11 -11
  460. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +11 -11
  461. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +11 -11
  462. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +11 -11
  463. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +11 -11
  464. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +11 -11
  465. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +11 -11
  466. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +11 -11
  467. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +11 -11
  468. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +11 -11
  469. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +11 -11
  470. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +11 -11
  471. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +11 -11
  472. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +11 -11
  473. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +11 -11
  474. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +11 -11
  475. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +11 -11
  476. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +11 -11
  477. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +11 -11
  478. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +11 -11
  479. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +11 -11
  480. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +11 -11
  481. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +11 -11
  482. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +11 -11
  483. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -11
  484. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -11
  485. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +11 -11
  486. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +11 -11
  487. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +11 -11
  488. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +11 -11
  489. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +11 -11
  490. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +11 -11
  491. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +11 -11
  492. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +11 -11
  493. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +11 -11
  494. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +11 -11
  495. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +11 -11
  496. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +11 -11
  497. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +11 -11
  498. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +11 -11
  499. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +11 -11
  500. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +11 -11
  501. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +11 -11
  502. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +11 -11
  503. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +11 -11
  504. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +11 -11
  505. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +11 -11
  506. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -11
  507. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +11 -11
  508. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +11 -11
  509. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +11 -11
  510. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +11 -11
  511. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +11 -11
  512. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +11 -11
  513. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +11 -11
  514. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +11 -11
  515. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +11 -11
  516. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +11 -11
  517. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +11 -11
  518. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +11 -11
  519. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +11 -11
  520. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +11 -11
  521. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +11 -11
  522. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +11 -11
  523. nautobot/project-static/docs/user-guide/index.html +11 -11
  524. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +11 -11
  525. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +11 -11
  526. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +11 -11
  527. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +11 -11
  528. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +11 -11
  529. nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -11
  530. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +11 -11
  531. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +11 -11
  532. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +11 -11
  533. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +11 -11
  534. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +11 -11
  535. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +11 -11
  536. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +11 -11
  537. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +11 -11
  538. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +11 -11
  539. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +11 -11
  540. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +11 -11
  541. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +11 -11
  542. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +11 -11
  543. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +11 -11
  544. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +11 -11
  545. nautobot/project-static/docs/user-guide/platform-functionality/note.html +11 -11
  546. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +11 -11
  547. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +11 -11
  548. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +11 -11
  549. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +11 -11
  550. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +11 -11
  551. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +11 -11
  552. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +11 -11
  553. nautobot/project-static/docs/user-guide/platform-functionality/role.html +11 -11
  554. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +11 -11
  555. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -11
  556. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +11 -11
  557. nautobot/project-static/docs/user-guide/platform-functionality/status.html +11 -11
  558. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +11 -11
  559. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +11 -11
  560. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +11 -11
  561. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +11 -11
  562. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +11 -11
  563. nautobot/tenancy/templates/tenancy/tenant.html +1 -7
  564. nautobot/tenancy/views.py +13 -0
  565. nautobot/users/templates/users/api_tokens.html +4 -4
  566. nautobot/users/templates/users/base.html +28 -28
  567. nautobot/virtualization/templates/virtualization/cluster.html +64 -64
  568. nautobot/virtualization/templates/virtualization/inc/virtualmachine_vminterface_filter.html +8 -0
  569. nautobot/virtualization/templates/virtualization/virtualmachine_component_add.html +25 -25
  570. nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +1 -251
  571. nautobot/virtualization/templates/virtualization/vminterface.html +70 -70
  572. nautobot/virtualization/urls.py +0 -12
  573. nautobot/virtualization/views.py +158 -54
  574. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +13 -13
  575. nautobot/wireless/tests/integration/test_radio_profile.py +1 -1
  576. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/METADATA +1 -1
  577. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/RECORD +581 -570
  578. nautobot/ipam/templates/ipam/prefix_ipaddresses.html +0 -11
  579. nautobot/ipam/templates/ipam/prefix_prefixes.html +0 -11
  580. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/LICENSE.txt +0 -0
  581. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/NOTICE +0 -0
  582. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/WHEEL +0 -0
  583. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/entry_points.txt +0 -0
@@ -2,88 +2,88 @@
2
2
  {% load helpers %}
3
3
 
4
4
  {% block content_left_page %}
5
- <div class="panel panel-default">
6
- <div class="panel-heading">
7
- <strong>Rear Port</strong>
8
- </div>
9
- <table class="table table-hover panel-body attr-table">
10
- <tr>
11
- {% if object.device %}
12
- <td>Device</td>
13
- <td>{{ object.device|hyperlinked_object }}</td>
14
- {% else %}
15
- <td>Module</td>
16
- <td>{{ object.module|hyperlinked_object }}</td>
17
- {% endif %}
18
- </tr>
19
- <tr>
20
- <td>Name</td>
21
- <td>{{ object.name }}</td>
22
- </tr>
23
- <tr>
24
- <td>Label</td>
25
- <td>{{ object.label|placeholder }}</td>
26
- </tr>
27
- <tr>
28
- <td>Type</td>
29
- <td>{{ object.get_type_display }}</td>
30
- </tr>
31
- <tr>
32
- <td>Positions</td>
33
- <td>{{ object.positions }}</td>
34
- </tr>
35
- <tr>
36
- <td>Description</td>
37
- <td>{{ object.description|placeholder }}</td>
38
- </tr>
39
- </table>
40
- </div>
5
+ <div class="panel panel-default">
6
+ <div class="panel-heading">
7
+ <strong>Rear Port</strong>
8
+ </div>
9
+ <table class="table table-hover panel-body attr-table">
10
+ <tr>
11
+ {% if object.device %}
12
+ <td>Device</td>
13
+ <td>{{ object.device|hyperlinked_object }}</td>
14
+ {% else %}
15
+ <td>Module</td>
16
+ <td>{{ object.module|hyperlinked_object }}</td>
17
+ {% endif %}
18
+ </tr>
19
+ <tr>
20
+ <td>Name</td>
21
+ <td>{{ object.name }}</td>
22
+ </tr>
23
+ <tr>
24
+ <td>Label</td>
25
+ <td>{{ object.label|placeholder }}</td>
26
+ </tr>
27
+ <tr>
28
+ <td>Type</td>
29
+ <td>{{ object.get_type_display }}</td>
30
+ </tr>
31
+ <tr>
32
+ <td>Positions</td>
33
+ <td>{{ object.positions }}</td>
34
+ </tr>
35
+ <tr>
36
+ <td>Description</td>
37
+ <td>{{ object.description|placeholder }}</td>
38
+ </tr>
39
+ </table>
40
+ </div>
41
41
  {% endblock content_left_page %}
42
42
 
43
43
  {% block content_right_page %}
44
- <div class="panel panel-default">
45
- <div class="panel-heading">
46
- <strong>Connection</strong>
47
- </div>
48
- {% if object.cable %}
49
- <table class="table table-hover panel-body attr-table">
50
- <tr>
51
- <td>Cable</td>
52
- <td>
53
- {{ object.cable|hyperlinked_object }}
54
- <a href="{% url 'dcim:rearport_trace' pk=object.pk %}" class="btn btn-primary btn-xs" title="Trace">
55
- <i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
56
- </a>
57
- </td>
58
- </tr>
59
- <tr>
60
- <td>Connection Status</td>
61
- <td>
62
- {% if object.cable.status %}
63
- <span class="label label-success">{{ object.cable.get_status_display }}</span>
64
- {% else %}
65
- <span class="label label-info">{{ object.cable.get_status_display }}</span>
66
- {% endif %}
67
- </td>
68
- </tr>
69
- </table>
70
- {% else %}
71
- <div class="panel-body text-muted">
72
- Not connected
73
- {% if perms.dcim.add_cable %}
74
- <span class="dropdown pull-right">
75
- <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
76
- <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
77
- </button>
78
- <ul class="dropdown-menu dropdown-menu-right">
79
- <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='interface' %}?return_url={{ object.get_absolute_url }}">Interface</a></li>
80
- <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
81
- <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
82
- <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
83
- </ul>
84
- </span>
44
+ <div class="panel panel-default">
45
+ <div class="panel-heading">
46
+ <strong>Connection</strong>
47
+ </div>
48
+ {% if object.cable %}
49
+ <table class="table table-hover panel-body attr-table">
50
+ <tr>
51
+ <td>Cable</td>
52
+ <td>
53
+ {{ object.cable|hyperlinked_object }}
54
+ <a href="{% url 'dcim:rearport_trace' pk=object.pk %}" class="btn btn-primary btn-xs" title="Trace">
55
+ <i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
56
+ </a>
57
+ </td>
58
+ </tr>
59
+ <tr>
60
+ <td>Connection Status</td>
61
+ <td>
62
+ {% if object.cable.status %}
63
+ <span class="label label-success">{{ object.cable.get_status_display }}</span>
64
+ {% else %}
65
+ <span class="label label-info">{{ object.cable.get_status_display }}</span>
85
66
  {% endif %}
86
- </div>
67
+ </td>
68
+ </tr>
69
+ </table>
70
+ {% else %}
71
+ <div class="panel-body text-muted">
72
+ Not connected
73
+ {% if perms.dcim.add_cable %}
74
+ <span class="dropdown pull-right">
75
+ <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
76
+ <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
77
+ </button>
78
+ <ul class="dropdown-menu dropdown-menu-right">
79
+ <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='interface' %}?return_url={{ object.get_absolute_url }}">Interface</a></li>
80
+ <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
81
+ <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
82
+ <li><a href="{% url 'dcim:rearport_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
83
+ </ul>
84
+ </span>
87
85
  {% endif %}
88
86
  </div>
87
+ {% endif %}
88
+ </div>
89
89
  {% endblock content_right_page %}
@@ -1,6 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
3
-
4
- {% block extra_breadcrumbs %}
5
- <li><a href="{% url 'dcim:device' pk=object.device.pk %}">{{ object.device }}</a></li>
6
- {% endblock extra_breadcrumbs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -9,7 +9,7 @@ from nautobot.core.testing.integration import (
9
9
  BulkOperationsTestCases,
10
10
  SeleniumTestCase,
11
11
  )
12
- from nautobot.dcim.models import Device
12
+ from nautobot.dcim.models import Controller, Device
13
13
  from nautobot.extras.tests.integration import create_test_device
14
14
 
15
15
 
@@ -25,6 +25,7 @@ class DeviceBulkOperationsTestCase(BulkOperationsTestCases.BulkOperationsTestCas
25
25
  model_class = Device
26
26
 
27
27
  def setup_items(self):
28
+ Controller.objects.all().delete()
28
29
  Device.objects.all().delete()
29
30
  test_uuid = str(uuid.uuid4())
30
31
 
@@ -77,7 +78,7 @@ class DeviceBulkUrlParamTestCase(SeleniumTestCase):
77
78
 
78
79
  # Click the bulk-edit button (it uses formaction)
79
80
  bulk_url = reverse("dcim:device_bulk_edit")
80
- btn_xpath = f'//button[@type="submit" and @formaction="{bulk_url}"]'
81
+ btn_xpath = f'//button[@type="submit" and starts-with(@formaction, "{bulk_url}")]'
81
82
  bulk_btn = WebDriverWait(self.browser.driver, 2).until(
82
83
  expected_conditions.element_to_be_clickable((By.XPATH, btn_xpath))
83
84
  )
@@ -17,10 +17,14 @@ class LocationBulkOperationsTestCase(BulkOperationsTestCases.BulkOperationsTestC
17
17
  model_edit_data = {"description": "Test description"}
18
18
  model_filter_by = {"location_type": "External"}
19
19
  model_class = Location
20
+ model_expected_counts: dict[str, int] = {
21
+ "all": 5,
22
+ "filtered": 2,
23
+ }
24
+ all_count = 5
20
25
 
21
26
  def setup_items(self):
22
- Location.objects.all().delete()
23
-
27
+ self.model_expected_counts["all"] = Location.objects.count() + self.all_count
24
28
  # Create locations for test
25
29
  self.create_location("Test Location Integration Test 1")
26
30
  self.create_location("Test Location Integration Test 2")
@@ -10,7 +10,7 @@ from django.urls import reverse
10
10
  from rest_framework import status
11
11
 
12
12
  from nautobot.core.testing import APITestCase, APIViewTestCases
13
- from nautobot.core.testing.utils import generate_random_device_asset_tag_of_specified_size
13
+ from nautobot.core.testing.utils import generate_random_device_asset_tag_of_specified_size, get_deletable_objects
14
14
  from nautobot.dcim.choices import (
15
15
  ConsolePortTypeChoices,
16
16
  InterfaceModeChoices,
@@ -3587,6 +3587,15 @@ class DeviceTypeToSoftwareImageFileTestCase(
3587
3587
  class ControllerTestCase(APIViewTestCases.APIViewTestCase):
3588
3588
  model = Controller
3589
3589
 
3590
+ def get_deletable_object(self):
3591
+ # This method is used in `test_recreate_object_csv`,
3592
+ # and the CSV export-import round-trip doesn't correctly distinguish between empty-list and null values presently,
3593
+ # so a `null` exported then re-imported will become a `[]` and cause the test to fail. Work around that for now:
3594
+ instance = get_deletable_objects(self.model, self._get_queryset().filter(capabilities__isnull=False)).first()
3595
+ if instance is None:
3596
+ self.fail("Couldn't find a single deletable object!")
3597
+ return instance
3598
+
3590
3599
  @classmethod
3591
3600
  def setUpTestData(cls):
3592
3601
  statuses = Status.objects.get_for_model(Controller)
@@ -3618,6 +3627,14 @@ class ControllerTestCase(APIViewTestCases.APIViewTestCase):
3618
3627
  "location": locations[2].pk,
3619
3628
  "capabilities": ["wireless"],
3620
3629
  },
3630
+ {
3631
+ "name": "Controller 4",
3632
+ "platform": platforms[3].pk,
3633
+ "status": statuses[3].pk,
3634
+ "role": roles[3].pk,
3635
+ "location": locations[3].pk,
3636
+ "capabilities": None,
3637
+ },
3621
3638
  ]
3622
3639
  cls.bulk_update_data = {
3623
3640
  "platform": platforms[0].pk,
@@ -3629,6 +3646,15 @@ class ControllerTestCase(APIViewTestCases.APIViewTestCase):
3629
3646
  class ControllerManagedDeviceGroupTestCase(APIViewTestCases.APIViewTestCase):
3630
3647
  model = ControllerManagedDeviceGroup
3631
3648
 
3649
+ def get_deletable_object(self):
3650
+ # This method is used in `test_recreate_object_csv`,
3651
+ # and the CSV export-import round-trip doesn't correctly distinguish between empty-list and null values presently,
3652
+ # so a `null` exported then re-imported will become a `[]` and cause the test to fail. Work around that for now:
3653
+ instance = get_deletable_objects(self.model, self._get_queryset().filter(capabilities__isnull=False)).first()
3654
+ if instance is None:
3655
+ self.fail("Couldn't find a single deletable object!")
3656
+ return instance
3657
+
3632
3658
  @classmethod
3633
3659
  def setUpTestData(cls):
3634
3660
  controllers = Controller.objects.all()
@@ -3651,6 +3677,12 @@ class ControllerManagedDeviceGroupTestCase(APIViewTestCases.APIViewTestCase):
3651
3677
  "weight": 200,
3652
3678
  "capabilities": ["wireless"],
3653
3679
  },
3680
+ {
3681
+ "name": "ControllerManagedDeviceGroup 4",
3682
+ "controller": controllers[3].pk,
3683
+ "weight": 200,
3684
+ "capabilities": None,
3685
+ },
3654
3686
  ]
3655
3687
  # changing controller is error-prone since a child group must have the same controller as its parent
3656
3688
  cls.update_data = {
@@ -7,7 +7,9 @@ from django.contrib.auth import get_user_model
7
7
  from django.contrib.contenttypes.models import ContentType
8
8
  from django.db.models import Q
9
9
  from django.test import override_settings
10
+ from django.test.client import RequestFactory
10
11
  from django.urls import reverse
12
+ from django.utils.html import strip_spaces_between_tags
11
13
  from netaddr import EUI
12
14
  import yaml
13
15
 
@@ -107,6 +109,7 @@ from nautobot.dcim.models import (
107
109
  from nautobot.dcim.views import (
108
110
  ConsoleConnectionsListView,
109
111
  InterfaceConnectionsListView,
112
+ LocationUIViewSet,
110
113
  PowerConnectionsListView,
111
114
  )
112
115
  from nautobot.extras.choices import CustomFieldTypeChoices, RelationshipTypeChoices
@@ -208,6 +211,8 @@ class LocationTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase, ViewT
208
211
 
209
212
  class LocationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
210
213
  model = Location
214
+ # One query for the natural slug, one for `LocationViewSet.get_extra_context`
215
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 2}
211
216
 
212
217
  @classmethod
213
218
  def setUpTestData(cls):
@@ -230,7 +235,14 @@ class LocationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
230
235
  status=status,
231
236
  description="Hi!",
232
237
  )
233
- for loc in [loc1, loc2, loc3, loc4]:
238
+ loc5 = Location.objects.create(
239
+ name="Leaf 2",
240
+ location_type=lt3,
241
+ parent=loc3,
242
+ status=status,
243
+ description="Hi!",
244
+ )
245
+ for loc in [loc1, loc2, loc3, loc4, loc5]:
234
246
  loc.validated_save()
235
247
 
236
248
  cls.form_data = {
@@ -429,10 +441,28 @@ class LocationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
429
441
  self.assertEqual(location.contact_phone, "")
430
442
  self.assertEqual(location.contact_email, "")
431
443
 
444
+ def test_get_extra_context(self):
445
+ view_set = LocationUIViewSet()
446
+ child_1, child_2 = Location.objects.filter(name__startswith="Leaf ")
447
+ parent_location = child_1.parent
448
+ child_1.location_type.content_types.add(ContentType.objects.get_for_model(Prefix))
449
+ status = Status.objects.get_for_model(Prefix).first()
450
+ prefix_1 = Prefix.objects.create(network="192.0.2.0", prefix_length=25, status=status)
451
+ prefix_2 = Prefix.objects.create(network="192.0.2.128", prefix_length=25, status=status)
452
+ prefix_1.locations.set([child_1, child_2])
453
+ prefix_2.locations.set([child_1, child_2])
454
+ request = RequestFactory().get(parent_location.get_absolute_url())
455
+ request.user = self.user
456
+ self.add_permissions("dcim.view_location")
457
+ self.add_permissions("ipam.view_prefix")
458
+ context = view_set.get_extra_context(request=request, instance=parent_location)
459
+ self.assertEqual(context["stats"]["prefix_count"], 2)
460
+
432
461
 
433
462
  class RackGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase, ViewTestCases.BulkEditObjectsViewTestCase):
434
463
  model = RackGroup
435
464
  sort_on_field = "name"
465
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
436
466
 
437
467
  @classmethod
438
468
  def setUpTestData(cls):
@@ -460,6 +490,7 @@ class RackGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase, ViewTest
460
490
 
461
491
  class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
462
492
  model = RackReservation
493
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
463
494
 
464
495
  @classmethod
465
496
  def setUpTestData(cls):
@@ -495,6 +526,7 @@ class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
495
526
 
496
527
  class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase):
497
528
  model = Rack
529
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
498
530
 
499
531
  @classmethod
500
532
  def setUpTestData(cls):
@@ -2081,6 +2113,7 @@ class PlatformTestCase(ViewTestCases.OrganizationalObjectViewTestCase, ViewTestC
2081
2113
 
2082
2114
  class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2083
2115
  model = Device
2116
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
2084
2117
 
2085
2118
  @classmethod
2086
2119
  def setUpTestData(cls):
@@ -2278,6 +2311,7 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2278
2311
  def test_vdc_panel_includes_add_vdc_btn(self):
2279
2312
  """Assert Add Virtual device Contexts button is in Device detail view: Issue from #6348"""
2280
2313
  device = Device.objects.first()
2314
+ self.add_permissions("dcim.add_virtualdevicecontext")
2281
2315
  url = reverse("dcim:device", kwargs={"pk": device.pk})
2282
2316
  response = self.client.get(url)
2283
2317
  response_body = extract_page_body(response.content.decode(response.charset))
@@ -2292,6 +2326,63 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2292
2326
  self.assertInHTML(expected_add_vdc_button_html, response_body)
2293
2327
  self.assertIn("Add virtual device context", response_body)
2294
2328
 
2329
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2330
+ def test_device_detail_with_parent_bay(self):
2331
+ parent_device = Device.objects.first()
2332
+ parent_device.subdevice_role = "parent"
2333
+ parent_device.validated_save()
2334
+ child_device = Device.objects.last()
2335
+ child_device.location = parent_device.location
2336
+ child_device.subdevice_role = "child"
2337
+ child_device.validated_save()
2338
+ device_bay = DeviceBay.objects.create(
2339
+ name="test device bay", device=parent_device, installed_device=child_device
2340
+ )
2341
+
2342
+ url = reverse("dcim:device", kwargs={"pk": child_device.pk})
2343
+ response = self.client.get(url)
2344
+ self.assertHttpStatus(response, 200)
2345
+ response_body = extract_page_body(response.content.decode(response.charset))
2346
+ self.assertInHTML(parent_device.display, response_body)
2347
+ self.assertInHTML(str(device_bay), response_body)
2348
+
2349
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2350
+ def test_device_detail_with_rack(self):
2351
+ device = Device.objects.filter(device_type__u_height__gt=0).first()
2352
+ self.assertIsNotNone(device)
2353
+ device.rack = Rack.objects.filter(u_height__gt=device.device_type.u_height).first()
2354
+ self.assertIsNotNone(device.rack)
2355
+ device.position = 1
2356
+ device.face = "front"
2357
+ device.validated_save()
2358
+ url = reverse("dcim:device", kwargs={"pk": device.pk})
2359
+ response = self.client.get(url)
2360
+ self.assertHttpStatus(response, 200)
2361
+ response_body = extract_page_body(response.content.decode(response.charset))
2362
+ self.assertInHTML(f"U{device.position} / {device.get_face_display()}", response_body)
2363
+
2364
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2365
+ def test_device_modulebays(self):
2366
+ device = Device.objects.filter(module_bays__isnull=True).first()
2367
+ module = Module.objects.filter(parent_module_bay__isnull=True).first()
2368
+
2369
+ module_bays = (
2370
+ ModuleBay.objects.create(parent_device=device, name="Test View Module Bay 1"),
2371
+ ModuleBay.objects.create(parent_device=device, name="Test View Module Bay 2"),
2372
+ ModuleBay.objects.create(parent_device=device, name="Test View Module Bay 3"),
2373
+ )
2374
+
2375
+ module.location = None
2376
+ module.parent_module_bay = module_bays[0]
2377
+ module.validated_save()
2378
+
2379
+ url = reverse("dcim:device_modulebays", kwargs={"pk": device.pk})
2380
+ response = self.client.get(url)
2381
+ self.assertHttpStatus(response, 200)
2382
+ # Custom badge - module count / module-bay count
2383
+ response_body = extract_page_body(response.content.decode(response.charset))
2384
+ self.assertInHTML("1/3", response_body)
2385
+
2295
2386
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2296
2387
  def test_device_consoleports(self):
2297
2388
  device = Device.objects.first()
@@ -2491,6 +2582,32 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2491
2582
  url = reverse("dcim:device_inventory", kwargs={"pk": device.pk})
2492
2583
  self.assertHttpStatus(self.client.get(url), 200)
2493
2584
 
2585
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2586
+ def test_device_wireless(self):
2587
+ self.add_permissions("dcim.view_controllermanageddevicegroup")
2588
+ device = Device.objects.first()
2589
+ device.controller_managed_device_group = ControllerManagedDeviceGroup.objects.first()
2590
+ device.validated_save()
2591
+ device.controller_managed_device_group.capabilities = ["wireless"]
2592
+ device.controller_managed_device_group.validated_save()
2593
+
2594
+ url = reverse("dcim:device_wireless", kwargs={"pk": device.pk})
2595
+ response = self.client.get(url)
2596
+ self.assertHttpStatus(response, 200)
2597
+
2598
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2599
+ def test_device_napalm_tabs(self):
2600
+ self.add_permissions("dcim.napalm_read_device")
2601
+ device = Device.objects.first()
2602
+ # TODO set NAPALM args, mock NAPALM APIs?
2603
+
2604
+ url = reverse("dcim:device_status", kwargs={"pk": device.pk})
2605
+ self.assertHttpStatus(self.client.get(url), 200)
2606
+ url = reverse("dcim:device_lldp_neighbors", kwargs={"pk": device.pk})
2607
+ self.assertHttpStatus(self.client.get(url), 200)
2608
+ url = reverse("dcim:device_config", kwargs={"pk": device.pk})
2609
+ self.assertHttpStatus(self.client.get(url), 200)
2610
+
2494
2611
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2495
2612
  def test_device_primary_ips(self):
2496
2613
  """Test assigning a primary IP to a device."""
@@ -2543,6 +2660,13 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2543
2660
  schema.pk,
2544
2661
  )
2545
2662
 
2663
+ url = reverse("dcim:device_configcontext", kwargs={"pk": self._get_queryset().get(name="Device X").pk})
2664
+ response = self.client.get(url)
2665
+ self.assertHttpStatus(response, 200)
2666
+ response_body = extract_page_body(response.content.decode(response.charset))
2667
+ self.assertIn("foo", response_body)
2668
+ self.assertIn("bar", response_body)
2669
+
2546
2670
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2547
2671
  def test_local_config_context_schema_validation_fails(self):
2548
2672
  """
@@ -2773,6 +2897,7 @@ class ModuleTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2773
2897
 
2774
2898
  class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase):
2775
2899
  model = ConsolePort
2900
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
2776
2901
 
2777
2902
  @classmethod
2778
2903
  def setUpTestData(cls):
@@ -2822,6 +2947,7 @@ class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase):
2822
2947
 
2823
2948
  class ConsoleServerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
2824
2949
  model = ConsoleServerPort
2950
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
2825
2951
 
2826
2952
  @classmethod
2827
2953
  def setUpTestData(cls):
@@ -2870,6 +2996,7 @@ class ConsoleServerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
2870
2996
 
2871
2997
  class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
2872
2998
  model = PowerPort
2999
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
2873
3000
 
2874
3001
  @classmethod
2875
3002
  def setUpTestData(cls):
@@ -2926,6 +3053,7 @@ class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
2926
3053
 
2927
3054
  class PowerOutletTestCase(ViewTestCases.DeviceComponentViewTestCase):
2928
3055
  model = PowerOutlet
3056
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
2929
3057
 
2930
3058
  @classmethod
2931
3059
  def setUpTestData(cls):
@@ -2995,6 +3123,7 @@ class PowerOutletTestCase(ViewTestCases.DeviceComponentViewTestCase):
2995
3123
 
2996
3124
  class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
2997
3125
  model = Interface
3126
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
2998
3127
 
2999
3128
  @classmethod
3000
3129
  def setUpTestData(cls):
@@ -3195,6 +3324,7 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
3195
3324
 
3196
3325
  class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
3197
3326
  model = FrontPort
3327
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
3198
3328
 
3199
3329
  @classmethod
3200
3330
  def setUpTestData(cls):
@@ -3310,6 +3440,7 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
3310
3440
 
3311
3441
  class RearPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
3312
3442
  model = RearPort
3443
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
3313
3444
 
3314
3445
  @classmethod
3315
3446
  def setUpTestData(cls):
@@ -3376,6 +3507,7 @@ class RearPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
3376
3507
 
3377
3508
  class DeviceBayTestCase(ViewTestCases.DeviceComponentViewTestCase):
3378
3509
  model = DeviceBay
3510
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
3379
3511
 
3380
3512
  @classmethod
3381
3513
  def setUpTestData(cls):
@@ -4185,7 +4317,11 @@ class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4185
4317
  Interface.objects.create(device=self.devices[0], name="eth0", status=interface_status)
4186
4318
  Interface.objects.create(device=self.devices[0], name="eth1", status=interface_status)
4187
4319
  response = self.client.get(reverse("dcim:device_interfaces", kwargs={"pk": self.devices[0].pk}))
4188
- self.assertBodyContains(response, "<th>Device</th>", html=True)
4320
+ self.assertBodyContains(
4321
+ response,
4322
+ '<th class="orderable"><a data-column-name="device" href="?sort=device">Device</a></th>',
4323
+ html=True,
4324
+ )
4189
4325
 
4190
4326
  def test_device_column_not_visible(self):
4191
4327
  """
@@ -4198,9 +4334,14 @@ class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4198
4334
  Interface.objects.create(device=self.devices[1], name="eth2", status=interface_status)
4199
4335
  Interface.objects.create(device=self.devices[1], name="eth3", status=interface_status)
4200
4336
  response = self.client.get(reverse("dcim:device_interfaces", kwargs={"pk": self.devices[1].pk}))
4201
- self.assertNotIn("<th >Device</th>", extract_page_body(response.content.decode(response.charset)))
4337
+ self.assertNotIn(
4338
+ '<th class="orderable"><a data-column-name="device" href="?sort=device">Device</a></th>',
4339
+ strip_spaces_between_tags(extract_page_body(response.content.decode(response.charset))),
4340
+ )
4202
4341
  # Sanity check:
4203
- self.assertBodyContains(response, "<th>Name</th>", html=True)
4342
+ self.assertBodyContains(
4343
+ response, '<th class="orderable"><a data-column-name="name" href="?sort=name">Name</a></th>', html=True
4344
+ )
4204
4345
 
4205
4346
  def test_set_master_after_adding_member(self):
4206
4347
  """Ensure master can be set for a member that was added via the Add Member flow."""
@@ -4246,6 +4387,7 @@ class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4246
4387
 
4247
4388
  class PowerPanelTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4248
4389
  model = PowerPanel
4390
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
4249
4391
 
4250
4392
  @classmethod
4251
4393
  def setUpTestData(cls):
@@ -4274,6 +4416,7 @@ class PowerPanelTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4274
4416
 
4275
4417
  class PowerFeedTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4276
4418
  model = PowerFeed
4419
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
4277
4420
 
4278
4421
  @classmethod
4279
4422
  def setUpTestData(cls):
@@ -4713,6 +4856,7 @@ class ControllerManagedDeviceGroupTestCase(ViewTestCases.PrimaryObjectViewTestCa
4713
4856
  class VirtualDeviceContextTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4714
4857
  model = VirtualDeviceContext
4715
4858
  filterset = VirtualDeviceContextFilterSet
4859
+ allowed_number_of_tree_queries_per_view_type = {"retrieve": 1}
4716
4860
 
4717
4861
  @classmethod
4718
4862
  def setUpTestData(cls):
nautobot/dcim/ui.py ADDED
@@ -0,0 +1,29 @@
1
+ from django.template import Context
2
+
3
+ from nautobot.core.ui.breadcrumbs import (
4
+ AncestorsBreadcrumbs,
5
+ InstanceBreadcrumbItem,
6
+ InstanceParentBreadcrumbItem,
7
+ ModelBreadcrumbItem,
8
+ )
9
+ from nautobot.core.views.utils import get_obj_from_context
10
+ from nautobot.dcim.models import Rack
11
+
12
+
13
+ class RackBreadcrumbs(AncestorsBreadcrumbs):
14
+ def get_detail_items(self, context: Context):
15
+ rack: Rack = get_obj_from_context(context)
16
+ base_items = [
17
+ ModelBreadcrumbItem(),
18
+ InstanceParentBreadcrumbItem(
19
+ parent_key="location",
20
+ ),
21
+ ]
22
+ detail_item = InstanceBreadcrumbItem(
23
+ label=self.detail_item_label,
24
+ )
25
+ if rack.rack_group:
26
+ ancestors_items = self.get_ancestors_items(rack.rack_group)
27
+ return [*base_items, *ancestors_items, InstanceBreadcrumbItem(instance=rack.rack_group), detail_item]
28
+
29
+ return [*base_items, detail_item]