nautobot 2.2.8__py3-none-any.whl → 2.3.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 (704) hide show
  1. nautobot/apps/forms.py +4 -0
  2. nautobot/apps/models.py +10 -1
  3. nautobot/circuits/__init__.py +0 -1
  4. nautobot/circuits/apps.py +1 -0
  5. nautobot/circuits/factory.py +15 -3
  6. nautobot/circuits/filters.py +13 -0
  7. nautobot/circuits/forms.py +13 -0
  8. nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
  9. nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
  10. nautobot/circuits/models.py +16 -3
  11. nautobot/circuits/tables.py +16 -2
  12. nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
  13. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
  14. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
  15. nautobot/circuits/tests/test_api.py +7 -5
  16. nautobot/circuits/tests/test_filters.py +12 -5
  17. nautobot/circuits/tests/test_models.py +33 -2
  18. nautobot/circuits/views.py +2 -3
  19. nautobot/cloud/__init__.py +0 -0
  20. nautobot/cloud/api/__init__.py +0 -0
  21. nautobot/cloud/api/serializers.py +54 -0
  22. nautobot/cloud/api/urls.py +16 -0
  23. nautobot/cloud/api/views.py +48 -0
  24. nautobot/cloud/apps.py +13 -0
  25. nautobot/cloud/factory.py +113 -0
  26. nautobot/cloud/filters.py +187 -0
  27. nautobot/cloud/forms.py +339 -0
  28. nautobot/cloud/homepage.py +43 -0
  29. nautobot/cloud/migrations/0001_initial.py +304 -0
  30. nautobot/cloud/migrations/__init__.py +0 -0
  31. nautobot/cloud/models.py +246 -0
  32. nautobot/cloud/navigation.py +85 -0
  33. nautobot/cloud/tables.py +157 -0
  34. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
  35. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +122 -0
  36. nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
  37. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +111 -0
  38. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +69 -0
  39. nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
  40. nautobot/cloud/tests/__init__.py +0 -0
  41. nautobot/cloud/tests/test_api.py +248 -0
  42. nautobot/cloud/tests/test_filters.py +125 -0
  43. nautobot/cloud/tests/test_models.py +43 -0
  44. nautobot/cloud/tests/test_views.py +153 -0
  45. nautobot/cloud/urls.py +14 -0
  46. nautobot/cloud/views.py +181 -0
  47. nautobot/core/__init__.py +0 -3
  48. nautobot/core/api/metadata.py +1 -0
  49. nautobot/core/api/parsers.py +7 -1
  50. nautobot/core/api/urls.py +1 -0
  51. nautobot/core/api/utils.py +1 -0
  52. nautobot/core/api/views.py +4 -0
  53. nautobot/core/apps/__init__.py +6 -3
  54. nautobot/core/constants.py +8 -0
  55. nautobot/core/factory.py +32 -1
  56. nautobot/core/filters.py +110 -14
  57. nautobot/core/forms/fields.py +10 -4
  58. nautobot/core/forms/forms.py +11 -3
  59. nautobot/core/forms/widgets.py +18 -1
  60. nautobot/core/graphql/generators.py +2 -2
  61. nautobot/core/graphql/schema.py +28 -7
  62. nautobot/core/jobs/__init__.py +20 -3
  63. nautobot/core/jobs/cleanup.py +100 -0
  64. nautobot/core/jobs/groups.py +38 -0
  65. nautobot/core/management/commands/generate_test_data.py +116 -3
  66. nautobot/core/models/__init__.py +34 -9
  67. nautobot/core/models/generics.py +19 -3
  68. nautobot/core/models/name_color_content_types.py +7 -28
  69. nautobot/core/models/querysets.py +4 -3
  70. nautobot/core/models/tree_queries.py +1 -1
  71. nautobot/core/models/utils.py +21 -5
  72. nautobot/core/settings.py +15 -19
  73. nautobot/core/settings.yaml +48 -13
  74. nautobot/core/settings_funcs.py +103 -0
  75. nautobot/core/tables.py +130 -56
  76. nautobot/core/templates/admin/search_form.html +1 -1
  77. nautobot/core/templates/buttons/add.html +11 -3
  78. nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
  79. nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
  80. nautobot/core/templates/buttons/export.html +101 -53
  81. nautobot/core/templates/buttons/job_import.html +11 -3
  82. nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
  83. nautobot/core/templates/generic/object_bulk_update.html +3 -1
  84. nautobot/core/templates/generic/object_changelog.html +0 -9
  85. nautobot/core/templates/generic/object_list.html +156 -17
  86. nautobot/core/templates/generic/object_retrieve.html +80 -16
  87. nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
  88. nautobot/core/templates/inc/javascript.html +2 -0
  89. nautobot/core/templates/inc/media.html +2 -2
  90. nautobot/core/templates/inc/nav_menu.html +1 -0
  91. nautobot/core/templates/inc/paginator.html +7 -7
  92. nautobot/core/templates/inc/search_panel.html +2 -2
  93. nautobot/core/templates/inc/table.html +2 -2
  94. nautobot/core/templates/nautobot_config.py.j2 +28 -8
  95. nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
  96. nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
  97. nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
  98. nautobot/core/templates/utilities/theme_preview.html +25 -8
  99. nautobot/core/templates/utilities/worker_status.html +152 -0
  100. nautobot/core/templatetags/buttons.py +335 -38
  101. nautobot/core/templatetags/form_helpers.py +1 -1
  102. nautobot/core/templatetags/helpers.py +181 -11
  103. nautobot/core/testing/api.py +5 -4
  104. nautobot/core/testing/filters.py +63 -14
  105. nautobot/core/testing/mixins.py +46 -0
  106. nautobot/core/testing/models.py +22 -0
  107. nautobot/core/testing/schema.py +4 -8
  108. nautobot/core/testing/views.py +31 -14
  109. nautobot/core/tests/integration/test_general_functionality.py +1 -1
  110. nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
  111. nautobot/core/tests/integration/test_swagger.py +1 -1
  112. nautobot/core/tests/nautobot_config.py +0 -1
  113. nautobot/core/tests/runner.py +2 -2
  114. nautobot/core/tests/test_api.py +1 -0
  115. nautobot/core/tests/test_authentication.py +7 -2
  116. nautobot/core/tests/test_filters.py +11 -9
  117. nautobot/core/tests/test_forms.py +9 -0
  118. nautobot/core/tests/test_graphql.py +27 -16
  119. nautobot/core/tests/test_jobs.py +204 -2
  120. nautobot/core/tests/test_tables.py +3 -1
  121. nautobot/core/tests/test_templatetags_helpers.py +12 -5
  122. nautobot/core/tests/test_templatetags_netutils.py +3 -3
  123. nautobot/core/tests/test_utils.py +31 -20
  124. nautobot/core/tests/test_views.py +6 -6
  125. nautobot/core/urls.py +8 -3
  126. nautobot/core/utils/deprecation.py +29 -0
  127. nautobot/core/utils/filtering.py +12 -9
  128. nautobot/core/utils/lookup.py +37 -2
  129. nautobot/core/utils/requests.py +4 -1
  130. nautobot/core/views/__init__.py +137 -24
  131. nautobot/core/views/generic.py +119 -67
  132. nautobot/core/views/mixins.py +105 -36
  133. nautobot/core/views/paginator.py +9 -3
  134. nautobot/core/views/renderers.py +121 -56
  135. nautobot/core/views/utils.py +81 -1
  136. nautobot/dcim/__init__.py +0 -1
  137. nautobot/dcim/api/serializers.py +180 -44
  138. nautobot/dcim/api/urls.py +7 -3
  139. nautobot/dcim/api/views.py +53 -7
  140. nautobot/dcim/apps.py +3 -0
  141. nautobot/dcim/choices.py +25 -0
  142. nautobot/dcim/constants.py +7 -0
  143. nautobot/dcim/factory.py +252 -18
  144. nautobot/dcim/filters/__init__.py +373 -193
  145. nautobot/dcim/filters/mixins.py +274 -1
  146. nautobot/dcim/forms.py +834 -121
  147. nautobot/dcim/graphql/types.py +2 -2
  148. nautobot/dcim/homepage.py +1 -1
  149. nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
  150. nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
  151. nautobot/dcim/migrations/0061_module_models.py +862 -0
  152. nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
  153. nautobot/dcim/models/__init__.py +8 -0
  154. nautobot/dcim/models/cables.py +15 -0
  155. nautobot/dcim/models/device_component_templates.py +207 -53
  156. nautobot/dcim/models/device_components.py +282 -99
  157. nautobot/dcim/models/devices.py +472 -13
  158. nautobot/dcim/models/racks.py +0 -1
  159. nautobot/dcim/navigation.py +47 -0
  160. nautobot/dcim/signals.py +3 -3
  161. nautobot/dcim/tables/__init__.py +35 -23
  162. nautobot/dcim/tables/devices.py +248 -47
  163. nautobot/dcim/tables/devicetypes.py +65 -9
  164. nautobot/dcim/tables/racks.py +5 -1
  165. nautobot/dcim/tables/template_code.py +46 -26
  166. nautobot/dcim/templates/dcim/cable_connect.html +76 -3
  167. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
  168. nautobot/dcim/templates/dcim/device/base.html +14 -6
  169. nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
  170. nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
  171. nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
  172. nautobot/dcim/templates/dcim/device/frontports.html +2 -3
  173. nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
  174. nautobot/dcim/templates/dcim/device/inventory.html +2 -3
  175. nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
  176. nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
  177. nautobot/dcim/templates/dcim/device/powerports.html +2 -3
  178. nautobot/dcim/templates/dcim/device/rearports.html +2 -3
  179. nautobot/dcim/templates/dcim/device.html +45 -1
  180. nautobot/dcim/templates/dcim/device_component.html +13 -5
  181. nautobot/dcim/templates/dcim/device_list.html +2 -1
  182. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +6 -0
  183. nautobot/dcim/templates/dcim/devicetype.html +99 -98
  184. nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
  185. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  186. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
  187. nautobot/dcim/templates/dcim/interface.html +17 -2
  188. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
  189. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  190. nautobot/dcim/templates/dcim/manufacturer.html +24 -0
  191. nautobot/dcim/templates/dcim/module/base.html +97 -0
  192. nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
  193. nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
  194. nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
  195. nautobot/dcim/templates/dcim/module_destroy.html +5 -0
  196. nautobot/dcim/templates/dcim/module_frontports.html +53 -0
  197. nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
  198. nautobot/dcim/templates/dcim/module_list.html +20 -0
  199. nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
  200. nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
  201. nautobot/dcim/templates/dcim/module_powerports.html +53 -0
  202. nautobot/dcim/templates/dcim/module_rearports.html +53 -0
  203. nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
  204. nautobot/dcim/templates/dcim/module_update.html +71 -0
  205. nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
  206. nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
  207. nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
  208. nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
  209. nautobot/dcim/templates/dcim/moduletype_retrieve.html +159 -0
  210. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
  211. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
  212. nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
  213. nautobot/dcim/tests/test_api.py +693 -208
  214. nautobot/dcim/tests/test_filters.py +843 -217
  215. nautobot/dcim/tests/test_models.py +1103 -8
  216. nautobot/dcim/tests/test_views.py +1525 -343
  217. nautobot/dcim/urls.py +17 -2
  218. nautobot/dcim/utils.py +2 -3
  219. nautobot/dcim/views.py +1109 -113
  220. nautobot/extras/__init__.py +0 -1
  221. nautobot/extras/api/serializers.py +115 -3
  222. nautobot/extras/api/urls.py +12 -0
  223. nautobot/extras/api/views.py +73 -59
  224. nautobot/extras/apps.py +2 -2
  225. nautobot/extras/choices.py +43 -0
  226. nautobot/extras/context_managers.py +13 -8
  227. nautobot/extras/datasources/git.py +2 -0
  228. nautobot/extras/factory.py +460 -9
  229. nautobot/extras/filters/__init__.py +174 -3
  230. nautobot/extras/filters/mixins.py +46 -43
  231. nautobot/extras/forms/base.py +24 -5
  232. nautobot/extras/forms/forms.py +227 -8
  233. nautobot/extras/forms/mixins.py +93 -0
  234. nautobot/extras/graphql/types.py +23 -10
  235. nautobot/extras/homepage.py +26 -3
  236. nautobot/extras/jobs.py +2 -2
  237. nautobot/extras/management/__init__.py +1 -0
  238. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
  239. nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
  240. nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
  241. nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
  242. nautobot/extras/migrations/0111_metadata.py +162 -0
  243. nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
  244. nautobot/extras/migrations/0113_saved_views.py +77 -0
  245. nautobot/extras/models/__init__.py +15 -1
  246. nautobot/extras/models/change_logging.py +3 -3
  247. nautobot/extras/models/contacts.py +4 -0
  248. nautobot/extras/models/customfields.py +18 -3
  249. nautobot/extras/models/groups.py +389 -225
  250. nautobot/extras/models/jobs.py +87 -3
  251. nautobot/extras/models/metadata.py +441 -0
  252. nautobot/extras/models/mixins.py +72 -62
  253. nautobot/extras/models/models.py +118 -9
  254. nautobot/extras/models/relationships.py +9 -2
  255. nautobot/extras/models/tags.py +13 -2
  256. nautobot/extras/navigation.py +57 -0
  257. nautobot/extras/plugins/__init__.py +3 -1
  258. nautobot/extras/querysets.py +30 -66
  259. nautobot/extras/signals.py +109 -101
  260. nautobot/extras/tables.py +201 -17
  261. nautobot/extras/templates/extras/dynamicgroup.html +44 -15
  262. nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
  263. nautobot/extras/templates/extras/job.html +1 -1
  264. nautobot/extras/templates/extras/job_detail.html +11 -0
  265. nautobot/extras/templates/extras/jobresult.html +61 -74
  266. nautobot/extras/templates/extras/metadatatype_create.html +89 -0
  267. nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
  268. nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
  269. nautobot/extras/templates/extras/objectchange_list.html +0 -12
  270. nautobot/extras/templates/extras/plugins_list.html +1 -3
  271. nautobot/extras/templates/extras/role_retrieve.html +48 -0
  272. nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
  273. nautobot/extras/tests/integration/test_customfields.py +1 -0
  274. nautobot/extras/tests/test_api.py +509 -23
  275. nautobot/extras/tests/test_changelog.py +20 -9
  276. nautobot/extras/tests/test_context_managers.py +22 -15
  277. nautobot/extras/tests/test_datasources.py +13 -1
  278. nautobot/extras/tests/test_dynamicgroups.py +201 -171
  279. nautobot/extras/tests/test_filters.py +211 -12
  280. nautobot/extras/tests/test_jobs.py +6 -6
  281. nautobot/extras/tests/test_models.py +501 -4
  282. nautobot/extras/tests/test_relationships.py +1 -0
  283. nautobot/extras/tests/test_views.py +586 -8
  284. nautobot/extras/tests/test_webhooks.py +1 -1
  285. nautobot/extras/urls.py +5 -0
  286. nautobot/extras/utils.py +85 -16
  287. nautobot/extras/views.py +562 -122
  288. nautobot/ipam/__init__.py +0 -1
  289. nautobot/ipam/apps.py +1 -0
  290. nautobot/ipam/factory.py +17 -19
  291. nautobot/ipam/filters.py +13 -0
  292. nautobot/ipam/forms.py +8 -4
  293. nautobot/ipam/graphql/types.py +2 -2
  294. nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
  295. nautobot/ipam/models.py +20 -20
  296. nautobot/ipam/querysets.py +1 -1
  297. nautobot/ipam/signals.py +4 -2
  298. nautobot/ipam/tables.py +5 -0
  299. nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
  300. nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
  301. nautobot/ipam/templates/ipam/prefix.html +1 -0
  302. nautobot/ipam/tests/test_api.py +37 -18
  303. nautobot/ipam/tests/test_filters.py +26 -2
  304. nautobot/ipam/tests/test_models.py +9 -2
  305. nautobot/ipam/tests/test_querysets.py +1 -1
  306. nautobot/ipam/tests/test_views.py +3 -2
  307. nautobot/ipam/urls.py +2 -2
  308. nautobot/ipam/views.py +20 -34
  309. nautobot/project-static/css/base.css +21 -0
  310. nautobot/project-static/css/dark.css +11 -0
  311. nautobot/project-static/docs/404.html +894 -90
  312. nautobot/project-static/docs/apps/index.html +894 -90
  313. nautobot/project-static/docs/apps/nautobot-apps.html +894 -90
  314. nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
  315. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
  316. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
  317. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +921 -122
  318. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +906 -103
  319. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1620 -905
  320. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +937 -146
  321. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +979 -190
  322. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +903 -101
  323. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +899 -95
  324. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +993 -195
  325. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +976 -133
  326. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1080 -274
  327. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1244 -336
  328. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1729 -877
  329. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1166 -383
  330. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2090 -1376
  331. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2248 -1424
  332. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +914 -113
  333. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +965 -165
  334. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1012 -225
  335. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1915 -1279
  336. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1848 -1104
  337. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +906 -103
  338. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2335 -1701
  339. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1804 -1026
  340. nautobot/project-static/docs/development/apps/api/configuration-view.html +894 -90
  341. nautobot/project-static/docs/development/apps/api/database-backend-config.html +894 -90
  342. nautobot/project-static/docs/development/apps/api/models/django-admin.html +894 -90
  343. nautobot/project-static/docs/development/apps/api/models/global-search.html +894 -90
  344. nautobot/project-static/docs/development/apps/api/models/graphql.html +894 -90
  345. nautobot/project-static/docs/development/apps/api/models/index.html +944 -92
  346. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +894 -90
  347. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +894 -90
  348. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +894 -90
  349. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +894 -90
  350. nautobot/project-static/docs/development/apps/api/platform-features/index.html +894 -90
  351. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +894 -90
  352. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +894 -90
  353. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +894 -90
  354. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +894 -90
  355. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +894 -90
  356. nautobot/project-static/docs/development/apps/api/prometheus.html +894 -90
  357. nautobot/project-static/docs/development/apps/api/setup.html +894 -90
  358. nautobot/project-static/docs/development/apps/api/testing.html +894 -90
  359. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +894 -90
  360. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +894 -90
  361. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +894 -90
  362. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +894 -90
  363. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +894 -90
  364. nautobot/project-static/docs/development/apps/api/views/base-template.html +894 -90
  365. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +894 -90
  366. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +894 -90
  367. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +894 -90
  368. nautobot/project-static/docs/development/apps/api/views/index.html +894 -90
  369. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +894 -90
  370. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +894 -90
  371. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +894 -90
  372. nautobot/project-static/docs/development/apps/api/views/notes.html +894 -90
  373. nautobot/project-static/docs/development/apps/api/views/rest-api.html +894 -90
  374. nautobot/project-static/docs/development/apps/api/views/urls.html +894 -90
  375. nautobot/project-static/docs/development/apps/index.html +894 -90
  376. nautobot/project-static/docs/development/apps/migration/code-updates.html +894 -90
  377. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +894 -90
  378. nautobot/project-static/docs/development/apps/migration/from-v1.html +894 -90
  379. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +894 -90
  380. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +894 -90
  381. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +894 -90
  382. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +894 -90
  383. nautobot/project-static/docs/development/apps/porting-from-netbox.html +894 -90
  384. nautobot/project-static/docs/development/core/application-registry.html +894 -90
  385. nautobot/project-static/docs/development/core/best-practices.html +895 -90
  386. nautobot/project-static/docs/development/core/bootstrap-ui.html +894 -90
  387. nautobot/project-static/docs/development/core/caching.html +894 -90
  388. nautobot/project-static/docs/development/core/controllers.html +894 -90
  389. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +894 -90
  390. nautobot/project-static/docs/development/core/generic-views.html +894 -90
  391. nautobot/project-static/docs/development/core/getting-started.html +894 -90
  392. nautobot/project-static/docs/development/core/homepage.html +894 -90
  393. nautobot/project-static/docs/development/core/index.html +905 -90
  394. nautobot/project-static/docs/development/core/model-checklist.html +903 -91
  395. nautobot/project-static/docs/development/core/model-features.html +894 -90
  396. nautobot/project-static/docs/development/core/natural-keys.html +894 -90
  397. nautobot/project-static/docs/development/core/navigation-menu.html +894 -90
  398. nautobot/project-static/docs/development/core/release-checklist.html +897 -93
  399. nautobot/project-static/docs/development/core/role-internals.html +894 -90
  400. nautobot/project-static/docs/development/core/settings.html +894 -90
  401. nautobot/project-static/docs/development/core/style-guide.html +895 -91
  402. nautobot/project-static/docs/development/core/templates.html +906 -91
  403. nautobot/project-static/docs/development/core/testing.html +894 -90
  404. nautobot/project-static/docs/development/core/user-preferences.html +894 -90
  405. nautobot/project-static/docs/development/index.html +894 -90
  406. nautobot/project-static/docs/development/jobs/index.html +1271 -453
  407. nautobot/project-static/docs/development/jobs/migration/from-v1.html +894 -90
  408. nautobot/project-static/docs/index.html +9032 -13
  409. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
  410. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
  411. nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
  412. nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
  413. nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
  414. nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
  415. nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
  416. nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
  417. nautobot/project-static/docs/models/dcim/module.html +15 -0
  418. nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
  419. nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
  420. nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
  421. nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
  422. nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
  423. nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
  424. nautobot/project-static/docs/models/extras/role.html +15 -0
  425. nautobot/project-static/docs/models/extras/savedview.html +15 -0
  426. nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
  427. nautobot/project-static/docs/models/extras/status.html +15 -0
  428. nautobot/project-static/docs/objects.inv +0 -0
  429. nautobot/project-static/docs/overview/application_stack.html +902 -91
  430. nautobot/project-static/docs/overview/design_philosophy.html +896 -92
  431. nautobot/project-static/docs/overview/index.html +13 -8228
  432. nautobot/project-static/docs/release-notes/index.html +1131 -94
  433. nautobot/project-static/docs/release-notes/version-1.0.html +894 -90
  434. nautobot/project-static/docs/release-notes/version-1.1.html +894 -90
  435. nautobot/project-static/docs/release-notes/version-1.2.html +894 -90
  436. nautobot/project-static/docs/release-notes/version-1.3.html +894 -90
  437. nautobot/project-static/docs/release-notes/version-1.4.html +894 -90
  438. nautobot/project-static/docs/release-notes/version-1.5.html +895 -91
  439. nautobot/project-static/docs/release-notes/version-1.6.html +895 -91
  440. nautobot/project-static/docs/release-notes/version-2.0.html +894 -90
  441. nautobot/project-static/docs/release-notes/version-2.1.html +894 -90
  442. nautobot/project-static/docs/release-notes/version-2.2.html +1137 -196
  443. nautobot/project-static/docs/release-notes/version-2.3.html +9954 -0
  444. nautobot/project-static/docs/requirements.txt +5 -5
  445. nautobot/project-static/docs/search/search_index.json +1 -1
  446. nautobot/project-static/docs/sitemap.xml +335 -260
  447. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  448. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +894 -90
  449. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +894 -90
  450. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +894 -90
  451. nautobot/project-static/docs/user-guide/administration/configuration/index.html +894 -90
  452. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1025 -175
  453. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +894 -90
  454. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +894 -90
  455. nautobot/project-static/docs/user-guide/administration/guides/caching.html +894 -90
  456. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +902 -90
  457. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +894 -90
  458. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +894 -90
  459. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +894 -90
  460. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +894 -90
  461. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +894 -90
  462. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +894 -90
  463. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +894 -90
  464. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +894 -90
  465. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +946 -155
  466. nautobot/project-static/docs/user-guide/administration/installation/index.html +903 -95
  467. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +936 -124
  468. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +956 -159
  469. nautobot/project-static/docs/user-guide/administration/installation/services.html +915 -114
  470. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +910 -101
  471. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +894 -90
  472. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +894 -90
  473. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +894 -90
  474. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +894 -90
  475. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +977 -121
  476. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +894 -90
  477. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +894 -90
  478. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +894 -90
  479. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +894 -90
  480. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +894 -90
  481. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +894 -90
  482. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +894 -90
  483. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +894 -90
  484. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +894 -90
  485. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +894 -90
  486. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +894 -90
  487. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +895 -91
  488. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +894 -90
  489. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +898 -90
  490. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +897 -93
  491. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
  492. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
  493. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
  494. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
  495. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
  496. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
  497. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +908 -104
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +925 -107
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +925 -107
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +920 -102
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +925 -107
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +908 -104
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +908 -104
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +915 -107
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +922 -118
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +923 -119
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +920 -116
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +908 -104
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +916 -107
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +928 -110
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +938 -120
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +930 -108
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +908 -104
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +939 -121
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +930 -112
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +920 -116
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +923 -119
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +925 -117
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +918 -114
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +908 -104
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +942 -85
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +926 -108
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +908 -104
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +945 -88
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +923 -105
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +931 -127
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +920 -116
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +908 -104
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +924 -106
  535. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +926 -108
  536. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +908 -104
  537. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +908 -104
  538. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +908 -104
  539. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +938 -90
  540. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +894 -90
  541. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +899 -91
  542. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +899 -91
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +894 -90
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +894 -90
  545. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +894 -90
  546. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +894 -90
  547. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +894 -90
  548. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +894 -90
  549. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +894 -90
  550. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +894 -90
  551. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +894 -90
  552. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +894 -90
  553. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +903 -98
  554. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +894 -90
  555. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +894 -90
  556. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +894 -90
  557. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +894 -90
  558. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +894 -90
  559. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +899 -91
  560. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +894 -90
  561. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +894 -90
  562. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +894 -90
  563. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +894 -90
  564. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +894 -90
  565. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +894 -90
  566. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +894 -90
  567. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +894 -90
  568. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +894 -90
  569. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +894 -90
  570. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +894 -90
  571. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +894 -90
  572. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +894 -90
  573. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
  574. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
  575. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
  576. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
  577. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
  578. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
  579. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
  580. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
  581. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
  582. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
  583. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
  584. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
  585. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
  586. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
  587. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
  588. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
  589. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
  590. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
  591. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
  592. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
  593. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
  594. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
  595. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
  596. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
  597. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
  598. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +894 -90
  599. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +894 -90
  600. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +894 -90
  601. nautobot/project-static/docs/user-guide/index.html +894 -90
  602. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +894 -90
  603. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +894 -90
  604. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +894 -90
  605. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +894 -90
  606. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1260 -787
  607. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +897 -93
  608. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +894 -90
  609. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +894 -90
  610. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +894 -90
  611. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +894 -90
  612. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +894 -90
  613. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +894 -90
  614. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +894 -90
  615. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +894 -90
  616. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +894 -90
  617. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +898 -90
  618. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +894 -90
  619. nautobot/project-static/docs/user-guide/platform-functionality/note.html +897 -93
  620. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
  621. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +897 -93
  622. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +894 -90
  623. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +894 -90
  624. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +894 -90
  625. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +894 -90
  626. nautobot/project-static/docs/user-guide/platform-functionality/role.html +897 -93
  627. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
  628. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +897 -93
  629. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
  630. nautobot/project-static/docs/user-guide/platform-functionality/status.html +894 -90
  631. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +894 -90
  632. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +952 -123
  633. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +894 -90
  634. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +894 -90
  635. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +894 -90
  636. nautobot/project-static/js/forms.js +71 -0
  637. nautobot/project-static/js/table_sorting_indicator.js +46 -0
  638. nautobot/project-static/js/tableconfig.js +6 -1
  639. nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
  640. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
  641. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
  642. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
  643. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
  644. nautobot/tenancy/__init__.py +0 -1
  645. nautobot/tenancy/apps.py +1 -0
  646. nautobot/tenancy/factory.py +3 -2
  647. nautobot/tenancy/filters/__init__.py +1 -0
  648. nautobot/tenancy/forms.py +1 -1
  649. nautobot/tenancy/templates/tenancy/tenant.html +24 -20
  650. nautobot/tenancy/views.py +11 -10
  651. nautobot/users/__init__.py +0 -1
  652. nautobot/users/api/serializers.py +1 -1
  653. nautobot/users/api/views.py +4 -2
  654. nautobot/users/apps.py +3 -2
  655. nautobot/users/factory.py +3 -3
  656. nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
  657. nautobot/users/models.py +12 -0
  658. nautobot/users/tests/test_filters.py +6 -3
  659. nautobot/users/urls.py +8 -0
  660. nautobot/virtualization/__init__.py +0 -1
  661. nautobot/virtualization/apps.py +1 -0
  662. nautobot/virtualization/filters.py +6 -1
  663. nautobot/virtualization/forms.py +11 -3
  664. nautobot/virtualization/graphql/types.py +2 -2
  665. nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
  666. nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
  667. nautobot/virtualization/models.py +0 -2
  668. nautobot/virtualization/tables.py +12 -8
  669. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  670. nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
  671. nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
  672. nautobot/virtualization/tests/test_api.py +9 -4
  673. nautobot/virtualization/tests/test_filters.py +22 -0
  674. nautobot/virtualization/tests/test_models.py +7 -3
  675. nautobot/virtualization/tests/test_views.py +19 -3
  676. nautobot/virtualization/urls.py +2 -2
  677. nautobot/virtualization/views.py +10 -32
  678. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/METADATA +21 -19
  679. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/RECORD +684 -564
  680. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
  681. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
  682. nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
  683. nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
  684. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
  685. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
  686. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
  687. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
  688. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
  689. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
  690. nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
  691. nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
  692. nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
  693. nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
  694. nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
  695. nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
  696. nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
  697. nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
  698. nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
  699. nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
  700. /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
  701. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
  702. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
  703. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
  704. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/entry_points.txt +0 -0
@@ -38,6 +38,7 @@ from nautobot.core.forms.constants import BOOLEAN_WITH_BLANK_CHOICES
38
38
  from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
39
39
  from nautobot.dcim.models import Device, DeviceRedundancyGroup, DeviceType, Location, Platform
40
40
  from nautobot.extras.choices import (
41
+ DynamicGroupTypeChoices,
41
42
  JobExecutionType,
42
43
  JobResultStatusChoices,
43
44
  ObjectChangeActionChoices,
@@ -50,6 +51,7 @@ from nautobot.extras.models import (
50
51
  ComputedField,
51
52
  ConfigContext,
52
53
  ConfigContextSchema,
54
+ Contact,
53
55
  CustomField,
54
56
  CustomFieldChoice,
55
57
  CustomLink,
@@ -64,21 +66,33 @@ from nautobot.extras.models import (
64
66
  JobButton,
65
67
  JobHook,
66
68
  JobResult,
69
+ MetadataChoice,
70
+ MetadataType,
67
71
  Note,
68
72
  ObjectChange,
73
+ ObjectMetadata,
69
74
  Relationship,
70
75
  RelationshipAssociation,
71
76
  Role,
77
+ SavedView,
72
78
  ScheduledJob,
73
79
  Secret,
74
80
  SecretsGroup,
75
81
  SecretsGroupAssociation,
82
+ StaticGroupAssociation,
76
83
  Status,
77
84
  Tag,
85
+ Team,
78
86
  Webhook,
79
87
  )
80
88
  from nautobot.extras.registry import registry
81
- from nautobot.extras.utils import ChangeLoggedModelsQuery, FeatureQuery, RoleModelsQuery, TaggableClassesQuery
89
+ from nautobot.extras.utils import (
90
+ ChangeLoggedModelsQuery,
91
+ FeatureQuery,
92
+ RoleModelsQuery,
93
+ TaggableClassesQuery,
94
+ )
95
+ from nautobot.tenancy.forms import TenancyFilterForm, TenancyForm
82
96
  from nautobot.tenancy.models import Tenant, TenantGroup
83
97
  from nautobot.virtualization.models import Cluster, ClusterGroup, VirtualMachine
84
98
 
@@ -111,6 +125,7 @@ __all__ = (
111
125
  "CustomFieldChoiceFormSet",
112
126
  "CustomLinkForm",
113
127
  "CustomLinkFilterForm",
128
+ "DynamicGroupBulkAssignForm",
114
129
  "DynamicGroupForm",
115
130
  "DynamicGroupFilterForm",
116
131
  "DynamicGroupMembershipFormSet",
@@ -139,9 +154,14 @@ __all__ = (
139
154
  "LocalContextFilterForm",
140
155
  "LocalContextModelForm",
141
156
  "LocalContextModelBulkEditForm",
157
+ "MetadataTypeBulkEditForm",
158
+ "MetadataTypeForm",
159
+ "MetadataTypeFilterForm",
160
+ "MetadataChoiceFormSet",
142
161
  "NoteForm",
143
162
  "NoteFilterForm",
144
163
  "ObjectChangeFilterForm",
164
+ "ObjectMetadataFilterForm",
145
165
  "PasswordInputWithPlaceholder",
146
166
  "RelationshipForm",
147
167
  "RelationshipFilterForm",
@@ -149,12 +169,15 @@ __all__ = (
149
169
  "RoleBulkEditForm",
150
170
  "RoleFilterForm",
151
171
  "RoleForm",
172
+ "SavedViewForm",
173
+ "SavedViewModalForm",
152
174
  "ScheduledJobFilterForm",
153
175
  "SecretForm",
154
176
  "SecretFilterForm",
155
177
  "SecretsGroupForm",
156
178
  "SecretsGroupFilterForm",
157
179
  "SecretsGroupAssociationFormSet",
180
+ "StaticGroupAssociationFilterForm",
158
181
  "StatusForm",
159
182
  "StatusFilterForm",
160
183
  "StatusBulkEditForm",
@@ -421,8 +444,8 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
421
444
  def __init__(self, *args, **kwargs):
422
445
  super().__init__(*args, **kwargs)
423
446
 
424
- if self.instance and self.instance.present_in_database:
425
- self.fields["key"].widget.attrs["readonly"] = True
447
+ if self.initial.get("key"):
448
+ self.fields["key"].disabled = True
426
449
 
427
450
 
428
451
  class CustomFieldFilterForm(NautobotFilterForm):
@@ -501,13 +524,14 @@ class CustomLinkFilterForm(BootstrapMixin, forms.Form):
501
524
  #
502
525
 
503
526
 
504
- class DynamicGroupForm(NautobotModelForm):
527
+ class DynamicGroupForm(TenancyForm, NautobotModelForm):
505
528
  """DynamicGroup model form."""
506
529
 
507
530
  content_type = CSVContentTypeField(
508
531
  queryset=ContentType.objects.filter(FeatureQuery("dynamic_groups").get_query()).order_by("app_label", "model"),
509
532
  label="Content Type",
510
533
  )
534
+ group_type = forms.ChoiceField(choices=DynamicGroupTypeChoices, widget=StaticSelect2())
511
535
 
512
536
  class Meta:
513
537
  model = DynamicGroup
@@ -515,6 +539,9 @@ class DynamicGroupForm(NautobotModelForm):
515
539
  "name",
516
540
  "description",
517
541
  "content_type",
542
+ "group_type",
543
+ "tenant",
544
+ "tags",
518
545
  ]
519
546
 
520
547
 
@@ -522,8 +549,13 @@ class DynamicGroupMembershipFormSetForm(forms.ModelForm):
522
549
  """DynamicGroupMembership model form for use inline on DynamicGroupFormSet."""
523
550
 
524
551
  group = DynamicModelChoiceField(
525
- queryset=DynamicGroup.objects.all(),
526
- query_params={"content_type": "$content_type"},
552
+ queryset=DynamicGroup.objects.filter(
553
+ group_type__in=[DynamicGroupTypeChoices.TYPE_DYNAMIC_FILTER, DynamicGroupTypeChoices.TYPE_DYNAMIC_SET]
554
+ ),
555
+ query_params={
556
+ "content_type": "$content_type",
557
+ "group_type": [DynamicGroupTypeChoices.TYPE_DYNAMIC_FILTER, DynamicGroupTypeChoices.TYPE_DYNAMIC_SET],
558
+ },
527
559
  )
528
560
 
529
561
  class Meta:
@@ -553,12 +585,110 @@ class DynamicGroupMembershipFormSet(BaseDynamicGroupMembershipFormSet):
553
585
  """
554
586
 
555
587
 
556
- class DynamicGroupFilterForm(BootstrapMixin, forms.Form):
588
+ class DynamicGroupFilterForm(TenancyFilterForm, NautobotFilterForm):
557
589
  """DynamicGroup filter form."""
558
590
 
559
591
  model = DynamicGroup
560
592
  q = forms.CharField(required=False, label="Search")
561
- content_type = MultipleContentTypeField(feature="dynamic_groups", choices_as_strings=True, label="Content Type")
593
+ content_type = MultipleContentTypeField(
594
+ feature="dynamic_groups", choices_as_strings=True, label="Content Type", required=False
595
+ )
596
+ tags = TagFilterField(model)
597
+
598
+
599
+ class DynamicGroupBulkAssignForm(BootstrapMixin, BulkEditForm):
600
+ content_type = forms.ModelChoiceField(
601
+ queryset=ContentType.objects.filter(FeatureQuery("dynamic_groups").get_query()).order_by("app_label", "model"),
602
+ widget=forms.HiddenInput(),
603
+ )
604
+ create_and_assign_to_new_group_name = forms.CharField(
605
+ required=False,
606
+ label="Create a new group",
607
+ help_text="Create a new group with this name and assign the selected objects to it.",
608
+ )
609
+
610
+ def __init__(self, model, *args, **kwargs):
611
+ super().__init__(model, *args, **kwargs)
612
+ self.fields["content_type"].initial = ContentType.objects.get_for_model(model)
613
+ self.fields["pk"] = forms.ModelMultipleChoiceField(
614
+ queryset=model.objects.all(),
615
+ widget=forms.MultipleHiddenInput(),
616
+ required=False,
617
+ )
618
+ self.fields["add_to_groups"] = DynamicModelMultipleChoiceField(
619
+ queryset=DynamicGroup.objects.filter(group_type=DynamicGroupTypeChoices.TYPE_STATIC),
620
+ required=False,
621
+ query_params={
622
+ "group_type": "static",
623
+ "content_type": model._meta.label_lower,
624
+ },
625
+ label="Add to existing group(s)",
626
+ )
627
+ self.fields["remove_from_groups"] = DynamicModelMultipleChoiceField(
628
+ queryset=DynamicGroup.objects.filter(group_type=DynamicGroupTypeChoices.TYPE_STATIC),
629
+ required=False,
630
+ query_params={
631
+ "group_type": "static",
632
+ "content_type": model._meta.label_lower,
633
+ },
634
+ label="Remove from group(s)",
635
+ )
636
+
637
+ class Meta:
638
+ nullable_fields = []
639
+
640
+ def clean(self):
641
+ data = super().clean()
642
+
643
+ if "add_to_groups" in data and "remove_from_groups" in data:
644
+ if data["add_to_groups"].filter(pk__in=data["remove_from_groups"].values_list("pk", flat=True)).exists():
645
+ raise ValidationError("Same group specified for both addition and removal")
646
+
647
+ return data
648
+
649
+
650
+ #
651
+ # Saved View
652
+ #
653
+
654
+
655
+ class SavedViewForm(BootstrapMixin, forms.ModelForm):
656
+ is_global_default = forms.BooleanField(
657
+ label="Is global default",
658
+ required=False,
659
+ help_text="If checked, this saved view will be used globally as the default saved view for this particular view",
660
+ )
661
+ is_shared = forms.BooleanField(
662
+ label="Is shared",
663
+ required=False,
664
+ help_text="If checked, all users will be able to see this saved view",
665
+ )
666
+
667
+ class Meta:
668
+ model = SavedView
669
+ fields = ["name", "is_global_default", "is_shared"]
670
+
671
+
672
+ class SavedViewModalForm(BootstrapMixin, forms.ModelForm):
673
+ is_shared = forms.BooleanField(
674
+ label="Is shared",
675
+ required=False,
676
+ help_text="If checked, all users will be able to see this saved view",
677
+ )
678
+
679
+ class Meta:
680
+ model = SavedView
681
+ fields = ["name", "config", "is_shared"]
682
+
683
+
684
+ class StaticGroupAssociationFilterForm(NautobotFilterForm):
685
+ model = StaticGroupAssociation
686
+ q = forms.CharField(required=False, label="Search")
687
+ dynamic_group = DynamicModelMultipleChoiceField(queryset=DynamicGroup.objects.all(), required=False)
688
+ assigned_object_type = CSVContentTypeField(
689
+ queryset=ContentType.objects.filter(FeatureQuery("dynamic_groups").get_query()).order_by("app_label", "model"),
690
+ required=False,
691
+ )
562
692
 
563
693
 
564
694
  #
@@ -1236,6 +1366,95 @@ class JobButtonFilterForm(BootstrapMixin, forms.Form):
1236
1366
  )
1237
1367
 
1238
1368
 
1369
+ #
1370
+ # Metadata
1371
+ #
1372
+
1373
+
1374
+ # MetadataChoice inline formset for use with providing dynamic rows when creating/editing choices
1375
+ # for `MetadataType` objects in UI views. Fields/exclude must be set but since we're using all the
1376
+ # fields we're just setting `exclude=()` here.
1377
+ MetadataChoiceFormSet = inlineformset_factory(
1378
+ parent_model=MetadataType,
1379
+ model=MetadataChoice,
1380
+ exclude=(),
1381
+ extra=5,
1382
+ widgets={
1383
+ "value": forms.TextInput(attrs={"class": "form-control"}),
1384
+ "weight": forms.NumberInput(attrs={"class": "form-control"}),
1385
+ },
1386
+ )
1387
+
1388
+
1389
+ class MetadataTypeForm(NautobotModelForm):
1390
+ name = forms.CharField(required=True, max_length=CHARFIELD_MAX_LENGTH)
1391
+ description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1392
+ content_types = MultipleContentTypeField(
1393
+ feature="metadata", help_text="The object(s) to which Metadata of this type can be applied."
1394
+ )
1395
+
1396
+ class Meta:
1397
+ model = MetadataType
1398
+ fields = (
1399
+ "name",
1400
+ "description",
1401
+ "data_type",
1402
+ "content_types",
1403
+ "tags",
1404
+ )
1405
+
1406
+ def __init__(self, *args, **kwargs):
1407
+ super().__init__(*args, **kwargs)
1408
+
1409
+ if self.initial.get("data_type"):
1410
+ self.fields["data_type"].disabled = True
1411
+
1412
+
1413
+ class MetadataTypeFilterForm(NautobotFilterForm):
1414
+ model = MetadataType
1415
+ q = forms.CharField(required=False, label="Search")
1416
+ content_types = MultipleContentTypeField(
1417
+ queryset=ContentType.objects.filter(FeatureQuery("metadata").get_query()),
1418
+ choices_as_strings=True,
1419
+ required=False,
1420
+ label="Content Type(s)",
1421
+ )
1422
+ tags = TagFilterField(model)
1423
+
1424
+
1425
+ class MetadataTypeBulkEditForm(NautobotBulkEditForm):
1426
+ pk = forms.ModelMultipleChoiceField(queryset=MetadataType.objects.all(), widget=forms.MultipleHiddenInput)
1427
+ description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1428
+
1429
+ class Meta:
1430
+ nullable_fields = [
1431
+ "description",
1432
+ ]
1433
+
1434
+
1435
+ class ObjectMetadataFilterForm(BootstrapMixin, forms.Form):
1436
+ model = ObjectMetadata
1437
+ q = forms.CharField(required=False, label="Search")
1438
+ contact = DynamicModelMultipleChoiceField(
1439
+ queryset=Contact.objects.all(),
1440
+ required=False,
1441
+ )
1442
+ team = DynamicModelMultipleChoiceField(
1443
+ queryset=Team.objects.all(),
1444
+ required=False,
1445
+ )
1446
+ assigned_object_type = MultipleContentTypeField(
1447
+ queryset=ContentType.objects.filter(FeatureQuery("metadata").get_query()),
1448
+ choices_as_strings=True,
1449
+ required=False,
1450
+ label="Content Type(s)",
1451
+ )
1452
+ metadata_type = DynamicModelMultipleChoiceField(
1453
+ queryset=MetadataType.objects.all(),
1454
+ required=False,
1455
+ )
1456
+
1457
+
1239
1458
  #
1240
1459
  # Notes
1241
1460
  #
@@ -13,17 +13,21 @@ from nautobot.core.forms import (
13
13
  )
14
14
  from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
15
15
  from nautobot.extras.choices import (
16
+ DynamicGroupTypeChoices,
16
17
  RelationshipSideChoices,
17
18
  RelationshipTypeChoices,
18
19
  )
19
20
  from nautobot.extras.models import (
21
+ Contact,
20
22
  CustomField,
23
+ DynamicGroup,
21
24
  Note,
22
25
  Relationship,
23
26
  RelationshipAssociation,
24
27
  Role,
25
28
  Status,
26
29
  Tag,
30
+ Team,
27
31
  )
28
32
  from nautobot.extras.utils import remove_prefix_from_cf_key
29
33
 
@@ -31,9 +35,11 @@ logger = logging.getLogger(__name__)
31
35
 
32
36
 
33
37
  __all__ = (
38
+ "ContactTeamModelFilterFormMixin",
34
39
  "CustomFieldModelBulkEditFormMixin",
35
40
  "CustomFieldModelFilterFormMixin",
36
41
  "CustomFieldModelFormMixin",
42
+ "DynamicGroupModelFormMixin",
37
43
  "NoteModelBulkEditFormMixin",
38
44
  "NoteModelFormMixin",
39
45
  "RelationshipModelBulkEditFormMixin",
@@ -49,6 +55,8 @@ __all__ = (
49
55
  "RelationshipModelForm",
50
56
  "RoleModelBulkEditFormMixin",
51
57
  "RoleModelFilterFormMixin",
58
+ "RoleNotRequiredModelFormMixin",
59
+ "RoleRequiredModelFormMixin",
52
60
  "StatusBulkEditFormMixin",
53
61
  "StatusFilterFormMixin",
54
62
  )
@@ -59,6 +67,30 @@ __all__ = (
59
67
  #
60
68
 
61
69
 
70
+ class ContactTeamModelFilterFormMixin(forms.Form):
71
+ """Adds the `contacts` and `teams` form fields to a filter form."""
72
+
73
+ def __init__(self, *args, **kwargs):
74
+ super().__init__(*args, **kwargs)
75
+
76
+ if getattr(self.model, "is_contact_associable_model", False):
77
+ if "contacts" not in self.fields:
78
+ self.fields["contacts"] = DynamicModelMultipleChoiceField(
79
+ required=False,
80
+ queryset=Contact.objects.all(),
81
+ to_field_name="name",
82
+ )
83
+
84
+ if "teams" not in self.fields:
85
+ self.fields["teams"] = DynamicModelMultipleChoiceField(
86
+ required=False,
87
+ queryset=Team.objects.all(),
88
+ to_field_name="name",
89
+ )
90
+
91
+ self.order_fields(self.field_order)
92
+
93
+
62
94
  class CustomFieldModelFilterFormMixin(forms.Form):
63
95
  def __init__(self, *args, **kwargs):
64
96
  super().__init__(*args, **kwargs)
@@ -135,6 +167,41 @@ class CustomFieldModelBulkEditFormMixin(BulkEditForm):
135
167
  self.custom_fields.append(field_name)
136
168
 
137
169
 
170
+ class DynamicGroupModelFormMixin(forms.ModelForm):
171
+ """
172
+ Mixin to add `dynamic_groups` field to model create/edit forms where applicable.
173
+ """
174
+
175
+ def __init__(self, *args, **kwargs):
176
+ super().__init__(*args, **kwargs)
177
+ if self._meta.model.is_dynamic_group_associable_model:
178
+ self.fields["dynamic_groups"] = DynamicModelMultipleChoiceField(
179
+ required=False,
180
+ initial=self.instance.dynamic_groups if self.instance else None,
181
+ queryset=(
182
+ DynamicGroup.objects.get_for_model(self._meta.model).filter(
183
+ group_type=DynamicGroupTypeChoices.TYPE_STATIC
184
+ )
185
+ ),
186
+ query_params={
187
+ "content_type": self._meta.model._meta.label_lower,
188
+ "group_type": DynamicGroupTypeChoices.TYPE_STATIC,
189
+ },
190
+ to_field_name="name",
191
+ help_text='Only Dynamic Groups of type "static" are selectable here.',
192
+ )
193
+
194
+ def save(self, commit=True):
195
+ obj = super().save(commit=commit)
196
+ if commit and obj.is_dynamic_group_associable_model:
197
+ current_groups = set(obj.dynamic_groups.filter(group_type=DynamicGroupTypeChoices.TYPE_STATIC))
198
+ for dynamic_group in set(self.cleaned_data.get("dynamic_groups")).difference(current_groups):
199
+ dynamic_group.add_members([obj])
200
+ for dynamic_group in current_groups.difference(self.cleaned_data.get("dynamic_groups")):
201
+ dynamic_group.remove_members([obj])
202
+ return obj
203
+
204
+
138
205
  class NoteFormBase(forms.Form):
139
206
  """Base for the NoteModelFormMixin and NoteModelBulkEditFormMixin."""
140
207
 
@@ -699,6 +766,32 @@ class RoleModelBulkEditFormMixin(forms.Form):
699
766
  self.order_fields(self.field_order) # Reorder fields again
700
767
 
701
768
 
769
+ class RoleNotRequiredModelFormMixin(forms.Form):
770
+ """Mixin to add non-required `role` choice field to forms."""
771
+
772
+ def __init__(self, *args, **kwargs):
773
+ super().__init__(*args, **kwargs)
774
+ self.fields["role"] = DynamicModelChoiceField(
775
+ required=False,
776
+ queryset=Role.objects.all(),
777
+ query_params={"content_types": self.model._meta.label_lower},
778
+ )
779
+ self.order_fields(self.field_order) # Reorder fields again
780
+
781
+
782
+ class RoleRequiredModelFormMixin(forms.Form):
783
+ """Mixin to add required `role` choice field to forms"""
784
+
785
+ def __init__(self, *args, **kwargs):
786
+ super().__init__(*args, **kwargs)
787
+ self.fields["role"] = DynamicModelChoiceField(
788
+ required=True,
789
+ queryset=Role.objects.all(),
790
+ query_params={"content_types": self.model._meta.label_lower},
791
+ )
792
+ self.order_fields(self.field_order) # Reorder fields again
793
+
794
+
702
795
  class RoleModelFilterFormMixin(forms.Form):
703
796
  """
704
797
  Mixin to add non-required `role` multiple-choice field to filter forms.
@@ -1,14 +1,27 @@
1
1
  from nautobot.core.graphql.types import OptimizedNautobotObjectType
2
- from nautobot.extras.filters import DynamicGroupFilterSet, StatusFilterSet, TagFilterSet
3
- from nautobot.extras.models import DynamicGroup, Status, Tag
2
+ from nautobot.extras.filters import (
3
+ ContactAssociationFilterSet,
4
+ DynamicGroupFilterSet,
5
+ StatusFilterSet,
6
+ TagFilterSet,
7
+ )
8
+ from nautobot.extras.models import ContactAssociation, DynamicGroup, Status, Tag
4
9
 
5
10
 
6
- class TagType(OptimizedNautobotObjectType):
7
- """Graphql Type Object for Tag model."""
11
+ class ContactAssociationType(OptimizedNautobotObjectType):
12
+ """GraphQL Type object for `ContactAssociation` model."""
8
13
 
9
14
  class Meta:
10
- model = Tag
11
- filterset_class = TagFilterSet
15
+ model = ContactAssociation
16
+ filterset_class = ContactAssociationFilterSet
17
+
18
+
19
+ class DynamicGroupType(OptimizedNautobotObjectType):
20
+ """Graphql Type object for `DynamicGroup` model."""
21
+
22
+ class Meta:
23
+ model = DynamicGroup
24
+ filterset_class = DynamicGroupFilterSet
12
25
 
13
26
 
14
27
  class StatusType(OptimizedNautobotObjectType):
@@ -19,9 +32,9 @@ class StatusType(OptimizedNautobotObjectType):
19
32
  filterset_class = StatusFilterSet
20
33
 
21
34
 
22
- class DynamicGroupType(OptimizedNautobotObjectType):
23
- """Graphql Type object for `DynamicGroup` model."""
35
+ class TagType(OptimizedNautobotObjectType):
36
+ """Graphql Type Object for Tag model."""
24
37
 
25
38
  class Meta:
26
- model = DynamicGroup
27
- filterset_class = DynamicGroupFilterSet
39
+ model = Tag
40
+ filterset_class = TagFilterSet
@@ -1,23 +1,46 @@
1
1
  from nautobot.core.apps import HomePageItem, HomePagePanel
2
2
  from nautobot.extras.choices import JobResultStatusChoices
3
- from nautobot.extras.models import GitRepository, JobResult, ObjectChange
3
+ from nautobot.extras.models import DynamicGroup, GitRepository, JobResult, ObjectChange
4
4
 
5
5
 
6
6
  def get_job_results(request):
7
7
  """Callback function to collect job history for panel."""
8
8
  return (
9
9
  JobResult.objects.filter(status__in=JobResultStatusChoices.READY_STATES)
10
- .defer("result")
10
+ .restrict(request.user, "view")
11
+ .only("id", "name", "status", "date_done", "user")
11
12
  .order_by("-date_done")[:10]
12
13
  )
13
14
 
14
15
 
15
16
  def get_changelog(request):
16
17
  """Callback function to collect changelog for panel."""
17
- return ObjectChange.objects.restrict(request.user, "view")[:15]
18
+ return ObjectChange.objects.restrict(request.user, "view").only(
19
+ "id",
20
+ "action",
21
+ "changed_object",
22
+ "changed_object_id",
23
+ "changed_object_type",
24
+ "object_repr",
25
+ "user_name",
26
+ "time",
27
+ )[:15]
18
28
 
19
29
 
20
30
  layout = (
31
+ HomePagePanel(
32
+ name="Organization",
33
+ items=(
34
+ HomePageItem(
35
+ name="Dynamic Groups",
36
+ link="extras:dynamicgroup_list",
37
+ model=DynamicGroup,
38
+ description="Groups of related objects",
39
+ permissions=["extras.view_dynamicgroup"],
40
+ weight=300,
41
+ ),
42
+ ),
43
+ ),
21
44
  HomePagePanel(
22
45
  name="Data Sources",
23
46
  weight=700,
nautobot/extras/jobs.py CHANGED
@@ -20,7 +20,7 @@ from django.conf import settings
20
20
  from django.contrib.auth import get_user_model
21
21
  from django.core.exceptions import ObjectDoesNotExist
22
22
  from django.core.files.base import ContentFile
23
- from django.core.files.uploadedfile import InMemoryUploadedFile
23
+ from django.core.files.uploadedfile import UploadedFile
24
24
  from django.core.validators import RegexValidator
25
25
  from django.db.models import Model
26
26
  from django.db.models.query import QuerySet
@@ -539,7 +539,7 @@ class BaseJob:
539
539
  elif isinstance(value, Model):
540
540
  return_data[field_name] = value.pk
541
541
  # FileVar (Save each FileVar as a FileProxy)
542
- elif isinstance(value, InMemoryUploadedFile):
542
+ elif isinstance(value, UploadedFile):
543
543
  return_data[field_name] = BaseJob._save_file_to_proxy(value)
544
544
  # IPAddressVar, IPAddressWithMaskVar, IPNetworkVar
545
545
  elif isinstance(value, netaddr.ip.BaseIP):
@@ -21,6 +21,7 @@ STATUS_CHOICESET_MAP = {
21
21
  "dcim.Device": dcim_choices.DeviceStatusChoices,
22
22
  "dcim.Interface": dcim_choices.InterfaceStatusChoices,
23
23
  "dcim.Location": dcim_choices.LocationStatusChoices,
24
+ "dcim.Module": dcim_choices.ModuleStatusChoices,
24
25
  "dcim.PowerFeed": dcim_choices.PowerFeedStatusChoices,
25
26
  "dcim.Rack": dcim_choices.RackStatusChoices,
26
27
  "dcim.DeviceRedundancyGroup": dcim_choices.DeviceRedundancyGroupStatusChoices,
@@ -1,11 +1,6 @@
1
- from django.apps import apps
2
- from django.core.cache import cache
3
1
  from django.core.management.base import BaseCommand
4
2
 
5
- from nautobot.core.utils.config import get_settings_or_config
6
3
  from nautobot.extras.models import DynamicGroup
7
- from nautobot.extras.querysets import DynamicGroupQuerySet
8
- from nautobot.extras.registry import registry
9
4
 
10
5
 
11
6
  class Command(BaseCommand):
@@ -14,17 +9,7 @@ class Command(BaseCommand):
14
9
  def handle(self, *args, **kwargs):
15
10
  """Run through all Dynamic Groups and ensure their member caches are up to date."""
16
11
 
17
- if get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT") == 0:
18
- self.stdout.write(
19
- self.style.NOTICE("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT is set to 0; skipping cache refresh")
20
- )
21
- else:
22
- self.stdout.write(self.style.NOTICE("Refreshing DynamicGroup member caches..."))
23
-
24
- for app_label in registry["model_features"]["dynamic_groups"]:
25
- for model_name in registry["model_features"]["dynamic_groups"][app_label]:
26
- model = apps.get_model(app_label=app_label, model_name=model_name)
27
- cache.delete(DynamicGroupQuerySet._get_eligible_dynamic_groups_cache_key(model))
12
+ self.stdout.write(self.style.NOTICE("Refreshing DynamicGroup member caches..."))
28
13
 
29
14
  dynamic_groups = DynamicGroup.objects.all()
30
15
 
@@ -66,6 +66,7 @@ def migrate_history(apps, schema_editor):
66
66
  for log_entry in LogEntry.objects.filter(content_type=custom_field_type, object_id=custom_field.id).order_by(
67
67
  "action_time"
68
68
  ):
69
+ action = None
69
70
  if log_entry.action_flag == ADDITION:
70
71
  action = ObjectChangeActionChoices.ACTION_CREATE
71
72
  if log_entry.action_flag == CHANGE: