nautobot 2.4.10__py3-none-any.whl → 2.4.12__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 (439) hide show
  1. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -114
  2. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +1 -1
  3. nautobot/circuits/views.py +76 -6
  4. nautobot/cloud/navigation.py +1 -1
  5. nautobot/cloud/tests/test_views.py +13 -1
  6. nautobot/cloud/views.py +39 -9
  7. nautobot/core/celery/__init__.py +21 -0
  8. nautobot/core/celery/encoders.py +3 -0
  9. nautobot/core/forms/forms.py +4 -1
  10. nautobot/core/jobs/bulk_actions.py +8 -8
  11. nautobot/core/jobs/cleanup.py +11 -0
  12. nautobot/core/management/commands/generate_test_data.py +2 -1
  13. nautobot/core/templates/components/panel/header_extra_content_table.html +12 -1
  14. nautobot/core/templates/components/panel/panel.html +4 -0
  15. nautobot/core/templates/generic/object_retrieve.html +2 -1
  16. nautobot/core/testing/mixins.py +19 -1
  17. nautobot/core/testing/views.py +104 -8
  18. nautobot/core/tests/test_jobs.py +20 -4
  19. nautobot/core/tests/test_utils.py +17 -0
  20. nautobot/core/tests/test_views.py +2 -2
  21. nautobot/core/tests/test_views_utils.py +53 -2
  22. nautobot/core/ui/object_detail.py +5 -1
  23. nautobot/core/utils/lookup.py +4 -2
  24. nautobot/core/utils/module_loading.py +23 -0
  25. nautobot/core/views/generic.py +2 -12
  26. nautobot/core/views/mixins.py +19 -1
  27. nautobot/core/views/renderers.py +4 -13
  28. nautobot/core/views/utils.py +16 -0
  29. nautobot/dcim/api/serializers.py +13 -0
  30. nautobot/dcim/api/urls.py +1 -0
  31. nautobot/dcim/api/views.py +20 -0
  32. nautobot/dcim/apps.py +1 -0
  33. nautobot/dcim/factory.py +11 -0
  34. nautobot/dcim/filters/__init__.py +116 -0
  35. nautobot/dcim/filters/mixins.py +2 -1
  36. nautobot/dcim/forms.py +205 -19
  37. nautobot/dcim/migrations/0070_modulefamily_models.py +92 -0
  38. nautobot/dcim/models/__init__.py +2 -0
  39. nautobot/dcim/models/device_component_templates.py +14 -0
  40. nautobot/dcim/models/device_components.py +13 -1
  41. nautobot/dcim/models/devices.py +72 -0
  42. nautobot/dcim/navigation.py +16 -0
  43. nautobot/dcim/tables/__init__.py +2 -0
  44. nautobot/dcim/tables/devices.py +50 -0
  45. nautobot/dcim/tables/devicetypes.py +35 -1
  46. nautobot/dcim/tables/template_code.py +2 -0
  47. nautobot/dcim/templates/dcim/controller/base.html +1 -9
  48. nautobot/dcim/templates/dcim/controller_retrieve.html +2 -83
  49. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +2 -25
  50. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +1 -90
  51. nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
  52. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +1 -63
  53. nautobot/dcim/templates/dcim/location.html +2 -249
  54. nautobot/dcim/templates/dcim/location_edit.html +2 -38
  55. nautobot/dcim/templates/dcim/location_retrieve.html +249 -0
  56. nautobot/dcim/templates/dcim/location_update.html +38 -0
  57. nautobot/dcim/templates/dcim/module_update.html +1 -0
  58. nautobot/dcim/templates/dcim/modulebay_retrieve.html +93 -1
  59. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +31 -0
  60. nautobot/dcim/templates/dcim/moduletype_retrieve.html +6 -0
  61. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -160
  62. nautobot/dcim/templates/dcim/virtualchassis.html +2 -51
  63. nautobot/dcim/templates/dcim/virtualchassis_add.html +2 -22
  64. nautobot/dcim/templates/dcim/virtualchassis_create.html +22 -0
  65. nautobot/dcim/templates/dcim/virtualchassis_edit.html +2 -93
  66. nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +51 -0
  67. nautobot/dcim/templates/dcim/virtualchassis_update.html +93 -0
  68. nautobot/dcim/tests/test_api.py +35 -0
  69. nautobot/dcim/tests/test_filters.py +102 -3
  70. nautobot/dcim/tests/test_models.py +146 -0
  71. nautobot/dcim/tests/test_views.py +70 -97
  72. nautobot/dcim/urls.py +5 -80
  73. nautobot/dcim/views.py +584 -342
  74. nautobot/extras/api/views.py +9 -2
  75. nautobot/extras/datasources/git.py +9 -1
  76. nautobot/extras/forms/forms.py +9 -5
  77. nautobot/extras/jobs.py +4 -2
  78. nautobot/extras/jobs_ui.py +208 -0
  79. nautobot/extras/models/datasources.py +5 -8
  80. nautobot/extras/models/jobs.py +5 -0
  81. nautobot/extras/models/tags.py +4 -0
  82. nautobot/extras/plugins/__init__.py +3 -0
  83. nautobot/extras/tables.py +40 -3
  84. nautobot/extras/templates/extras/configcontext.html +2 -220
  85. nautobot/extras/templates/extras/configcontext_edit.html +2 -50
  86. nautobot/extras/templates/extras/configcontext_retrieve.html +2 -0
  87. nautobot/extras/templates/extras/configcontext_update.html +50 -0
  88. nautobot/extras/templates/extras/configcontextschema.html +2 -48
  89. nautobot/extras/templates/extras/configcontextschema_edit.html +2 -19
  90. nautobot/extras/templates/extras/configcontextschema_retrieve.html +48 -0
  91. nautobot/extras/templates/extras/configcontextschema_update.html +19 -0
  92. nautobot/extras/templates/extras/inc/configcontext_data.html +1 -0
  93. nautobot/extras/templates/extras/inc/configcontext_format.html +6 -0
  94. nautobot/extras/templates/extras/job_detail.html +1 -326
  95. nautobot/extras/templates/extras/job_edit.html +12 -6
  96. nautobot/extras/templates/extras/tag.html +2 -52
  97. nautobot/extras/templates/extras/tag_edit.html +2 -15
  98. nautobot/extras/templates/extras/tag_retrieve.html +2 -0
  99. nautobot/extras/templates/extras/tag_update.html +15 -0
  100. nautobot/extras/templates/extras/team_retrieve.html +2 -2
  101. nautobot/extras/tests/test_api.py +15 -15
  102. nautobot/extras/tests/test_filters.py +4 -4
  103. nautobot/extras/tests/test_jobs.py +23 -10
  104. nautobot/extras/tests/test_models.py +19 -8
  105. nautobot/extras/tests/test_plugins.py +6 -3
  106. nautobot/extras/tests/test_views.py +66 -11
  107. nautobot/extras/urls.py +4 -134
  108. nautobot/extras/views.py +186 -178
  109. nautobot/ipam/models.py +19 -4
  110. nautobot/ipam/tables.py +19 -0
  111. nautobot/ipam/templates/ipam/vlan.html +2 -84
  112. nautobot/ipam/templates/ipam/vlan_edit.html +2 -24
  113. nautobot/ipam/templates/ipam/vlan_retrieve.html +84 -0
  114. nautobot/ipam/templates/ipam/vlan_update.html +24 -0
  115. nautobot/ipam/tests/test_views.py +5 -0
  116. nautobot/ipam/urls.py +1 -21
  117. nautobot/ipam/views.py +45 -70
  118. nautobot/project-static/docs/404.html +33 -10
  119. nautobot/project-static/docs/apps/index.html +33 -10
  120. nautobot/project-static/docs/apps/nautobot-apps.html +33 -10
  121. nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js → bundle.56ea9cef.min.js} +2 -2
  122. nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js.map → bundle.56ea9cef.min.js.map} +2 -2
  123. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +33 -10
  124. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +33 -10
  125. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +33 -10
  126. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +33 -10
  127. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +33 -10
  128. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +33 -10
  129. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +33 -10
  130. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +33 -10
  131. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +33 -10
  132. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +33 -10
  133. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +33 -10
  134. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +33 -10
  135. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +33 -10
  136. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +33 -10
  137. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +33 -10
  138. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +33 -10
  139. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +33 -10
  140. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +33 -10
  141. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +33 -10
  142. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +122 -10
  143. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +33 -10
  144. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +33 -10
  145. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +33 -10
  146. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +33 -10
  147. nautobot/project-static/docs/development/apps/api/configuration-view.html +33 -10
  148. nautobot/project-static/docs/development/apps/api/database-backend-config.html +33 -10
  149. nautobot/project-static/docs/development/apps/api/models/django-admin.html +33 -10
  150. nautobot/project-static/docs/development/apps/api/models/global-search.html +33 -10
  151. nautobot/project-static/docs/development/apps/api/models/graphql.html +33 -10
  152. nautobot/project-static/docs/development/apps/api/models/index.html +33 -10
  153. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +42 -10
  154. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +33 -10
  155. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +33 -10
  156. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +33 -10
  157. nautobot/project-static/docs/development/apps/api/platform-features/index.html +33 -10
  158. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +33 -10
  159. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +33 -10
  160. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +33 -10
  161. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -11
  162. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +33 -10
  163. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +33 -10
  164. nautobot/project-static/docs/development/apps/api/prometheus.html +33 -10
  165. nautobot/project-static/docs/development/apps/api/setup.html +33 -10
  166. nautobot/project-static/docs/development/apps/api/testing.html +33 -10
  167. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +33 -10
  168. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +33 -10
  169. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +33 -10
  170. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +33 -10
  171. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +33 -10
  172. nautobot/project-static/docs/development/apps/api/views/base-template.html +33 -10
  173. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +33 -10
  174. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +33 -10
  175. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +33 -10
  176. nautobot/project-static/docs/development/apps/api/views/index.html +33 -10
  177. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +33 -10
  178. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +33 -10
  179. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +33 -10
  180. nautobot/project-static/docs/development/apps/api/views/notes.html +33 -10
  181. nautobot/project-static/docs/development/apps/api/views/rest-api.html +33 -10
  182. nautobot/project-static/docs/development/apps/api/views/urls.html +33 -10
  183. nautobot/project-static/docs/development/apps/index.html +33 -10
  184. nautobot/project-static/docs/development/apps/migration/code-updates.html +33 -10
  185. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +33 -10
  186. nautobot/project-static/docs/development/apps/migration/from-v1.html +33 -10
  187. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +33 -10
  188. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +33 -10
  189. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +33 -10
  190. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +33 -10
  191. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +33 -10
  192. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +33 -10
  193. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +33 -10
  194. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +33 -10
  195. nautobot/project-static/docs/development/apps/porting-from-netbox.html +33 -10
  196. nautobot/project-static/docs/development/core/application-registry.html +33 -10
  197. nautobot/project-static/docs/development/core/best-practices.html +33 -10
  198. nautobot/project-static/docs/development/core/bootstrap-ui.html +33 -10
  199. nautobot/project-static/docs/development/core/caching.html +33 -10
  200. nautobot/project-static/docs/development/core/controllers.html +33 -10
  201. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +33 -10
  202. nautobot/project-static/docs/development/core/generic-views.html +33 -10
  203. nautobot/project-static/docs/development/core/getting-started.html +33 -10
  204. nautobot/project-static/docs/development/core/homepage.html +33 -10
  205. nautobot/project-static/docs/development/core/index.html +33 -10
  206. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +33 -10
  207. nautobot/project-static/docs/development/core/model-checklist.html +33 -10
  208. nautobot/project-static/docs/development/core/model-features.html +33 -10
  209. nautobot/project-static/docs/development/core/natural-keys.html +33 -10
  210. nautobot/project-static/docs/development/core/navigation-menu.html +33 -10
  211. nautobot/project-static/docs/development/core/release-checklist.html +33 -10
  212. nautobot/project-static/docs/development/core/role-internals.html +33 -10
  213. nautobot/project-static/docs/development/core/settings.html +33 -10
  214. nautobot/project-static/docs/development/core/style-guide.html +33 -10
  215. nautobot/project-static/docs/development/core/templates.html +33 -10
  216. nautobot/project-static/docs/development/core/testing.html +33 -10
  217. nautobot/project-static/docs/development/core/ui-component-framework.html +33 -10
  218. nautobot/project-static/docs/development/core/user-preferences.html +33 -10
  219. nautobot/project-static/docs/development/index.html +33 -10
  220. nautobot/project-static/docs/development/jobs/getting-started.html +33 -10
  221. nautobot/project-static/docs/development/jobs/index.html +33 -10
  222. nautobot/project-static/docs/development/jobs/installation.html +33 -10
  223. nautobot/project-static/docs/development/jobs/job-extensions.html +33 -10
  224. nautobot/project-static/docs/development/jobs/job-logging.html +33 -10
  225. nautobot/project-static/docs/development/jobs/job-patterns.html +33 -10
  226. nautobot/project-static/docs/development/jobs/job-structure.html +33 -10
  227. nautobot/project-static/docs/development/jobs/migration/from-v1.html +33 -10
  228. nautobot/project-static/docs/development/jobs/testing.html +33 -10
  229. nautobot/project-static/docs/index.html +33 -10
  230. nautobot/project-static/docs/insert-analytics.sh +36 -0
  231. nautobot/project-static/docs/objects.inv +0 -0
  232. nautobot/project-static/docs/overview/application_stack.html +33 -10
  233. nautobot/project-static/docs/overview/design_philosophy.html +33 -10
  234. nautobot/project-static/docs/release-notes/index.html +33 -10
  235. nautobot/project-static/docs/release-notes/version-1.0.html +33 -10
  236. nautobot/project-static/docs/release-notes/version-1.1.html +33 -10
  237. nautobot/project-static/docs/release-notes/version-1.2.html +33 -10
  238. nautobot/project-static/docs/release-notes/version-1.3.html +33 -10
  239. nautobot/project-static/docs/release-notes/version-1.4.html +33 -10
  240. nautobot/project-static/docs/release-notes/version-1.5.html +33 -10
  241. nautobot/project-static/docs/release-notes/version-1.6.html +33 -10
  242. nautobot/project-static/docs/release-notes/version-2.0.html +33 -10
  243. nautobot/project-static/docs/release-notes/version-2.1.html +33 -10
  244. nautobot/project-static/docs/release-notes/version-2.2.html +33 -10
  245. nautobot/project-static/docs/release-notes/version-2.3.html +33 -10
  246. nautobot/project-static/docs/release-notes/version-2.4.html +363 -10
  247. nautobot/project-static/docs/requirements.txt +1 -1
  248. nautobot/project-static/docs/search/search_index.json +1 -1
  249. nautobot/project-static/docs/sitemap.xml +302 -298
  250. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  251. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +33 -10
  252. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +33 -10
  253. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +33 -10
  254. nautobot/project-static/docs/user-guide/administration/configuration/index.html +33 -10
  255. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +33 -10
  256. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +33 -10
  257. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +33 -10
  258. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +33 -10
  259. nautobot/project-static/docs/user-guide/administration/guides/docker.html +33 -10
  260. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +33 -10
  261. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +33 -10
  262. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +33 -10
  263. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +33 -10
  264. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +33 -10
  265. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +33 -10
  266. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +33 -10
  267. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +33 -10
  268. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +33 -10
  269. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +33 -10
  270. nautobot/project-static/docs/user-guide/administration/installation/index.html +33 -10
  271. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +33 -10
  272. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +33 -10
  273. nautobot/project-static/docs/user-guide/administration/installation/services.html +33 -10
  274. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +33 -10
  275. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +33 -10
  276. nautobot/project-static/docs/user-guide/administration/security/index.html +33 -10
  277. nautobot/project-static/docs/user-guide/administration/security/notices.html +33 -10
  278. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +33 -10
  279. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +33 -10
  280. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +33 -10
  281. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +33 -10
  282. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +33 -10
  283. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +33 -10
  284. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +33 -10
  285. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +33 -10
  286. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +33 -10
  287. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +33 -10
  288. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +33 -10
  289. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +33 -10
  290. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +33 -10
  291. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +33 -10
  292. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +33 -10
  293. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +33 -10
  294. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +33 -10
  295. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +33 -10
  296. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +33 -10
  297. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +33 -10
  298. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +33 -10
  299. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +33 -10
  300. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +33 -10
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +33 -10
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +33 -10
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +33 -10
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +33 -10
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +33 -10
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +33 -10
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +33 -10
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +33 -10
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +33 -10
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +33 -10
  311. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +33 -10
  312. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +45 -22
  313. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +33 -10
  314. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +33 -10
  315. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +33 -10
  316. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +33 -10
  317. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +33 -10
  318. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +33 -10
  319. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +33 -10
  320. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +33 -10
  321. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +33 -10
  322. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +33 -10
  323. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +37 -10
  324. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -10
  325. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +37 -10
  326. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +10261 -0
  327. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +36 -13
  328. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +33 -10
  329. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +33 -10
  330. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +33 -10
  331. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +33 -10
  332. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +33 -10
  333. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +33 -10
  334. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +33 -10
  335. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +33 -10
  336. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +33 -10
  337. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +33 -10
  338. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +33 -10
  339. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +33 -10
  340. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +33 -10
  341. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +33 -10
  342. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +33 -10
  343. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +33 -10
  344. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +33 -10
  345. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +33 -10
  346. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +33 -10
  347. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +33 -10
  348. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +33 -10
  349. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +33 -10
  350. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +33 -10
  351. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +33 -10
  352. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +33 -10
  353. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +33 -10
  354. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +33 -10
  355. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +33 -10
  356. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +33 -10
  357. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +33 -10
  358. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +33 -10
  359. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +33 -10
  360. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +33 -10
  361. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +33 -10
  362. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +33 -10
  363. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +33 -10
  364. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +33 -10
  365. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +33 -10
  366. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +33 -10
  367. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +33 -10
  368. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +33 -10
  369. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +33 -10
  370. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +33 -10
  371. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +33 -10
  372. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +33 -10
  373. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +33 -10
  374. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +33 -10
  375. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +33 -10
  376. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +33 -10
  377. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +33 -10
  378. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +33 -10
  379. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +33 -10
  380. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -18
  381. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +33 -10
  382. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +33 -10
  383. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +33 -10
  384. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +33 -10
  385. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +33 -10
  386. nautobot/project-static/docs/user-guide/index.html +33 -10
  387. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +33 -10
  388. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +33 -10
  389. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +33 -10
  390. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +33 -10
  391. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +33 -10
  392. nautobot/project-static/docs/user-guide/platform-functionality/events.html +33 -10
  393. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +33 -10
  394. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +33 -10
  395. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +39 -11
  396. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +33 -10
  397. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +33 -10
  398. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +33 -10
  399. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +33 -10
  400. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +33 -10
  401. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +33 -10
  402. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +33 -10
  403. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +33 -10
  404. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +33 -10
  405. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +33 -10
  406. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +33 -10
  407. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +33 -10
  408. nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -10
  409. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +33 -10
  410. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +33 -10
  411. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +33 -10
  412. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +33 -10
  413. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +33 -10
  414. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +33 -10
  415. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +33 -10
  416. nautobot/project-static/docs/user-guide/platform-functionality/role.html +33 -10
  417. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +33 -10
  418. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +33 -10
  419. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +33 -10
  420. nautobot/project-static/docs/user-guide/platform-functionality/status.html +33 -10
  421. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +33 -10
  422. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +33 -10
  423. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +33 -10
  424. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +33 -10
  425. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +33 -10
  426. nautobot/tenancy/tables.py +2 -0
  427. nautobot/virtualization/tests/test_views.py +1 -1
  428. nautobot/wireless/forms.py +0 -1
  429. nautobot/wireless/models.py +1 -1
  430. nautobot/wireless/navigation.py +1 -1
  431. nautobot/wireless/tables.py +18 -3
  432. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/METADATA +4 -4
  433. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/RECORD +439 -419
  434. /nautobot/dcim/templates/dcim/{platform_edit.html → platform_create.html} +0 -0
  435. /nautobot/extras/test_jobs/{pass.py → pass_job.py} +0 -0
  436. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/LICENSE.txt +0 -0
  437. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/NOTICE +0 -0
  438. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/WHEEL +0 -0
  439. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/entry_points.txt +0 -0
nautobot/extras/views.py CHANGED
@@ -2,6 +2,7 @@ import logging
2
2
  from typing import Optional
3
3
  from urllib.parse import parse_qs
4
4
 
5
+ from django.conf import settings
5
6
  from django.contrib import messages
6
7
  from django.contrib.contenttypes.models import ContentType
7
8
  from django.core.exceptions import ObjectDoesNotExist, ValidationError
@@ -15,7 +16,7 @@ from django.urls import reverse
15
16
  from django.urls.exceptions import NoReverseMatch
16
17
  from django.utils import timezone
17
18
  from django.utils.encoding import iri_to_uri
18
- from django.utils.html import format_html
19
+ from django.utils.html import format_html, format_html_join
19
20
  from django.utils.http import url_has_allowed_host_and_scheme
20
21
  from django.utils.timezone import get_current_timezone
21
22
  from django.views.generic import View
@@ -25,6 +26,7 @@ from rest_framework.decorators import action
25
26
  from rest_framework.permissions import IsAuthenticated
26
27
 
27
28
  from nautobot.apps.ui import BaseTextPanel
29
+ from nautobot.core.choices import ButtonActionColorChoices
28
30
  from nautobot.core.constants import PAGINATE_COUNT_DEFAULT
29
31
  from nautobot.core.events import publish_event
30
32
  from nautobot.core.exceptions import FilterSetFieldNotFound
@@ -79,14 +81,13 @@ from nautobot.ipam.tables import IPAddressTable, PrefixTable, VLANTable
79
81
  from nautobot.virtualization.models import VirtualMachine, VMInterface
80
82
  from nautobot.virtualization.tables import VirtualMachineTable, VMInterfaceTable
81
83
 
82
- from . import filters, forms, tables
84
+ from . import filters, forms, jobs_ui, tables
83
85
  from .api import serializers
84
86
  from .choices import (
85
87
  DynamicGroupTypeChoices,
86
88
  JobExecutionType,
87
89
  JobQueueTypeChoices,
88
90
  JobResultStatusChoices,
89
- LogLevelChoices,
90
91
  )
91
92
  from .datasources import (
92
93
  enqueue_git_repository_diff_origin_and_local,
@@ -111,7 +112,6 @@ from .models import (
111
112
  Job as JobModel,
112
113
  JobButton,
113
114
  JobHook,
114
- JobLogEntry,
115
115
  JobQueue,
116
116
  JobResult,
117
117
  MetadataType,
@@ -180,55 +180,89 @@ class ComputedFieldUIViewSet(NautobotUIViewSet):
180
180
  # have an associated owner, such as a Git repository
181
181
 
182
182
 
183
- class ConfigContextListView(generic.ObjectListView):
183
+ class ConfigContextUIViewSet(NautobotUIViewSet):
184
+ bulk_update_form_class = forms.ConfigContextBulkEditForm
185
+ filterset_class = filters.ConfigContextFilterSet
186
+ filterset_form_class = forms.ConfigContextFilterForm
187
+ form_class = forms.ConfigContextForm
184
188
  queryset = ConfigContext.objects.all()
185
- filterset = filters.ConfigContextFilterSet
186
- filterset_form = forms.ConfigContextFilterForm
187
- table = tables.ConfigContextTable
188
- action_buttons = ("add",)
189
+ serializer_class = serializers.ConfigContextSerializer
190
+ table_class = tables.ConfigContextTable
189
191
 
192
+ class AssignmentObjectFieldsPanel(object_detail.ObjectFieldsPanel):
193
+ def render_value(self, key, value, context):
194
+ if key == "dynamic_groups" and not settings.CONFIG_CONTEXT_DYNAMIC_GROUPS_ENABLED:
195
+ return None
196
+ if not value:
197
+ return helpers.HTML_NONE
190
198
 
191
- class ConfigContextView(generic.ObjectView):
192
- queryset = ConfigContext.objects.all()
199
+ items = []
200
+ for val in value.all():
201
+ rendered_val = helpers.hyperlinked_object(val)
202
+ items.append(rendered_val)
203
+
204
+ if not items:
205
+ return helpers.HTML_NONE
206
+
207
+ return format_html("<ul>{}</ul>", format_html_join("", "<li>{}</li>", ((item,) for item in items)))
208
+
209
+ object_detail_content = object_detail.ObjectDetailContent(
210
+ panels=(
211
+ object_detail.ObjectFieldsPanel(
212
+ weight=100,
213
+ section=SectionChoices.LEFT_HALF,
214
+ fields="__all__",
215
+ exclude_fields=[
216
+ "data",
217
+ "owner_content_type",
218
+ "owner_object_id",
219
+ ],
220
+ hide_if_unset=[
221
+ "owner",
222
+ ],
223
+ ),
224
+ object_detail.Panel(
225
+ weight=100,
226
+ section=SectionChoices.FULL_WIDTH,
227
+ label="Data",
228
+ header_extra_content_template_path="extras/inc/configcontext_format.html",
229
+ body_content_template_path="extras/inc/configcontext_data.html",
230
+ ),
231
+ AssignmentObjectFieldsPanel(
232
+ weight=200,
233
+ section=SectionChoices.RIGHT_HALF,
234
+ label="Assignment",
235
+ fields=[
236
+ "locations",
237
+ "roles",
238
+ "device_types",
239
+ "platforms",
240
+ "cluster_groups",
241
+ "clusters",
242
+ "tenant_groups",
243
+ "tenants",
244
+ "device_redundancy_groups",
245
+ "dynamic_groups",
246
+ ],
247
+ ),
248
+ )
249
+ )
193
250
 
194
251
  def get_extra_context(self, request, instance):
195
252
  context = super().get_extra_context(request, instance)
196
253
  # Determine user's preferred output format
197
- if request.GET.get("format") in ["json", "yaml"]:
198
- context["format"] = request.GET.get("format")
254
+ if request.GET.get("data_format") in ["json", "yaml"]:
255
+ context["data_format"] = request.GET.get("data_format")
199
256
  if request.user.is_authenticated:
200
- request.user.set_config("extras.configcontext.format", context["format"], commit=True)
257
+ request.user.set_config("extras.configcontext.format", context["data_format"], commit=True)
201
258
  elif request.user.is_authenticated:
202
- context["format"] = request.user.get_config("extras.configcontext.format", "json")
259
+ context["data_format"] = request.user.get_config("extras.configcontext.format", "json")
203
260
  else:
204
- context["format"] = "json"
261
+ context["data_format"] = "json"
205
262
 
206
263
  return context
207
264
 
208
265
 
209
- class ConfigContextEditView(generic.ObjectEditView):
210
- queryset = ConfigContext.objects.all()
211
- model_form = forms.ConfigContextForm
212
- template_name = "extras/configcontext_edit.html"
213
-
214
-
215
- class ConfigContextBulkEditView(generic.BulkEditView):
216
- queryset = ConfigContext.objects.all()
217
- filterset = filters.ConfigContextFilterSet
218
- table = tables.ConfigContextTable
219
- form = forms.ConfigContextBulkEditForm
220
-
221
-
222
- class ConfigContextDeleteView(generic.ObjectDeleteView):
223
- queryset = ConfigContext.objects.all()
224
-
225
-
226
- class ConfigContextBulkDeleteView(generic.BulkDeleteView):
227
- queryset = ConfigContext.objects.all()
228
- table = tables.ConfigContextTable
229
- filterset = filters.ConfigContextFilterSet
230
-
231
-
232
266
  class ObjectConfigContextView(generic.ObjectView):
233
267
  base_template = None
234
268
  template_name = "extras/object_configcontext.html"
@@ -263,28 +297,26 @@ class ObjectConfigContextView(generic.ObjectView):
263
297
  # have an associated owner, such as a Git repository
264
298
 
265
299
 
266
- class ConfigContextSchemaListView(generic.ObjectListView):
267
- queryset = ConfigContextSchema.objects.all()
268
- filterset = filters.ConfigContextSchemaFilterSet
269
- filterset_form = forms.ConfigContextSchemaFilterForm
270
- table = tables.ConfigContextSchemaTable
271
- action_buttons = ("add",)
272
-
273
-
274
- class ConfigContextSchemaView(generic.ObjectView):
300
+ class ConfigContextSchemaUIViewSet(NautobotUIViewSet):
301
+ bulk_update_form_class = forms.ConfigContextSchemaBulkEditForm
302
+ filterset_class = filters.ConfigContextSchemaFilterSet
303
+ filterset_form_class = forms.ConfigContextSchemaFilterForm
304
+ form_class = forms.ConfigContextSchemaForm
275
305
  queryset = ConfigContextSchema.objects.all()
306
+ serializer_class = serializers.ConfigContextSchemaSerializer
307
+ table_class = tables.ConfigContextSchemaTable
276
308
 
277
309
  def get_extra_context(self, request, instance):
278
310
  context = super().get_extra_context(request, instance)
279
311
  # Determine user's preferred output format
280
- if request.GET.get("format") in ["json", "yaml"]:
281
- context["format"] = request.GET.get("format")
312
+ if request.GET.get("data_format") in ["json", "yaml"]:
313
+ context["data_format"] = request.GET.get("data_format")
282
314
  if request.user.is_authenticated:
283
- request.user.set_config("extras.configcontextschema.format", context["format"], commit=True)
315
+ request.user.set_config("extras.configcontextschema.format", context["data_format"], commit=True)
284
316
  elif request.user.is_authenticated:
285
- context["format"] = request.user.get_config("extras.configcontextschema.format", "json")
317
+ context["data_format"] = request.user.get_config("extras.configcontextschema.format", "json")
286
318
  else:
287
- context["format"] = "json"
319
+ context["data_format"] = "json"
288
320
 
289
321
  return context
290
322
 
@@ -372,29 +404,6 @@ class ConfigContextSchemaObjectValidationView(generic.ObjectView):
372
404
  }
373
405
 
374
406
 
375
- class ConfigContextSchemaEditView(generic.ObjectEditView):
376
- queryset = ConfigContextSchema.objects.all()
377
- model_form = forms.ConfigContextSchemaForm
378
- template_name = "extras/configcontextschema_edit.html"
379
-
380
-
381
- class ConfigContextSchemaBulkEditView(generic.BulkEditView):
382
- queryset = ConfigContextSchema.objects.all()
383
- filterset = filters.ConfigContextSchemaFilterSet
384
- table = tables.ConfigContextSchemaTable
385
- form = forms.ConfigContextSchemaBulkEditForm
386
-
387
-
388
- class ConfigContextSchemaDeleteView(generic.ObjectDeleteView):
389
- queryset = ConfigContextSchema.objects.all()
390
-
391
-
392
- class ConfigContextSchemaBulkDeleteView(generic.BulkDeleteView):
393
- queryset = ConfigContextSchema.objects.all()
394
- table = tables.ConfigContextSchemaTable
395
- filterset = filters.ConfigContextSchemaFilterSet
396
-
397
-
398
407
  #
399
408
  # Contacts
400
409
  #
@@ -1293,8 +1302,6 @@ class ImageAttachmentDeleteView(generic.ObjectDeleteView):
1293
1302
  #
1294
1303
  # Jobs
1295
1304
  #
1296
-
1297
-
1298
1305
  class JobListView(generic.ObjectListView):
1299
1306
  """
1300
1307
  Retrieve all of the available jobs from disk and the recorded JobResult (if any) for each.
@@ -1546,6 +1553,64 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
1546
1553
  class JobView(generic.ObjectView):
1547
1554
  queryset = JobModel.objects.all()
1548
1555
  template_name = "extras/job_detail.html"
1556
+ object_detail_content = object_detail.ObjectDetailContent(
1557
+ panels=[
1558
+ object_detail.ObjectFieldsPanel(
1559
+ weight=100,
1560
+ section=SectionChoices.LEFT_HALF,
1561
+ label="Source Code",
1562
+ fields=[
1563
+ "module_name",
1564
+ "job_class_name",
1565
+ "class_path",
1566
+ "installed",
1567
+ "is_job_hook_receiver",
1568
+ "is_job_button_receiver",
1569
+ ],
1570
+ ),
1571
+ jobs_ui.JobObjectFieldsPanel(
1572
+ weight=200,
1573
+ section=SectionChoices.LEFT_HALF,
1574
+ label="Job",
1575
+ fields=["grouping", "name", "description", "enabled"],
1576
+ ),
1577
+ object_detail.ObjectsTablePanel(
1578
+ weight=100,
1579
+ section=SectionChoices.FULL_WIDTH,
1580
+ table_class=tables.JobResultTable,
1581
+ table_title="JobResults",
1582
+ table_filter=["job_model"],
1583
+ ),
1584
+ jobs_ui.JobObjectFieldsPanel(
1585
+ weight=100,
1586
+ section=SectionChoices.RIGHT_HALF,
1587
+ label="Properties",
1588
+ fields=[
1589
+ "approval_required",
1590
+ "supports_dryrun",
1591
+ "dryrun_default",
1592
+ "read_only",
1593
+ "hidden",
1594
+ "has_sensitive_variables",
1595
+ "is_singleton",
1596
+ "soft_time_limit",
1597
+ "time_limit",
1598
+ "job_queues",
1599
+ "default_job_queue",
1600
+ ],
1601
+ ),
1602
+ ],
1603
+ extra_buttons=[
1604
+ jobs_ui.JobRunScheduleButton(
1605
+ weight=100,
1606
+ link_name="extras:job_run",
1607
+ label="Run/Schedule",
1608
+ icon="mdi-play",
1609
+ color=ButtonActionColorChoices.SUBMIT,
1610
+ required_permissions=["extras.job_run"],
1611
+ ),
1612
+ ],
1613
+ )
1549
1614
 
1550
1615
 
1551
1616
  class JobEditView(generic.ObjectEditView):
@@ -1553,6 +1618,11 @@ class JobEditView(generic.ObjectEditView):
1553
1618
  model_form = forms.JobEditForm
1554
1619
  template_name = "extras/job_edit.html"
1555
1620
 
1621
+ def alter_obj(self, obj, request, url_args, url_kwargs):
1622
+ # Reload the job class to ensure we have the latest version
1623
+ get_job(obj.class_path, reload=True)
1624
+ return obj
1625
+
1556
1626
 
1557
1627
  class JobBulkEditView(generic.BulkEditView):
1558
1628
  queryset = JobModel.objects.all()
@@ -2077,44 +2147,12 @@ class JobHookUIViewSet(NautobotUIViewSet):
2077
2147
  #
2078
2148
 
2079
2149
 
2080
- def get_annotated_jobresult_queryset():
2081
- return (
2082
- JobResult.objects.defer("result")
2083
- .select_related("job_model", "user")
2084
- .annotate(
2085
- debug_log_count=count_related(
2086
- JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_DEBUG}
2087
- ),
2088
- success_log_count=count_related(
2089
- JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_SUCCESS}
2090
- ),
2091
- info_log_count=count_related(
2092
- JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_INFO}
2093
- ),
2094
- warning_log_count=count_related(
2095
- JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_WARNING}
2096
- ),
2097
- error_log_count=count_related(
2098
- JobLogEntry,
2099
- "job_result",
2100
- filter_dict={
2101
- "log_level__in": [
2102
- LogLevelChoices.LOG_FAILURE,
2103
- LogLevelChoices.LOG_ERROR,
2104
- LogLevelChoices.LOG_CRITICAL,
2105
- ],
2106
- },
2107
- ),
2108
- )
2109
- )
2110
-
2111
-
2112
2150
  class JobResultListView(generic.ObjectListView):
2113
2151
  """
2114
2152
  List JobResults
2115
2153
  """
2116
2154
 
2117
- queryset = get_annotated_jobresult_queryset()
2155
+ queryset = JobResult.objects.defer("result").select_related("job_model", "user")
2118
2156
  filterset = filters.JobResultFilterSet
2119
2157
  filterset_form = forms.JobResultFilterForm
2120
2158
  table = tables.JobResultTable
@@ -2126,7 +2164,7 @@ class JobResultDeleteView(generic.ObjectDeleteView):
2126
2164
 
2127
2165
 
2128
2166
  class JobResultBulkDeleteView(generic.BulkDeleteView):
2129
- queryset = get_annotated_jobresult_queryset()
2167
+ queryset = JobResult.objects.defer("result").select_related("job_model", "user")
2130
2168
  table = tables.JobResultTable
2131
2169
  filterset = filters.JobResultFilterSet
2132
2170
 
@@ -2519,24 +2557,15 @@ class RelationshipUIViewSet(NautobotUIViewSet):
2519
2557
  )
2520
2558
 
2521
2559
 
2522
- class RelationshipAssociationListView(generic.ObjectListView):
2560
+ class RelationshipAssociationUIViewSet(ObjectListViewMixin, ObjectDestroyViewMixin, ObjectBulkDestroyViewMixin):
2561
+ filterset_class = filters.RelationshipAssociationFilterSet
2562
+ filterset_form_class = forms.RelationshipAssociationFilterForm
2563
+ serializer_class = serializers.RelationshipAssociationSerializer
2564
+ table_class = tables.RelationshipAssociationTable
2523
2565
  queryset = RelationshipAssociation.objects.all()
2524
- filterset = filters.RelationshipAssociationFilterSet
2525
- filterset_form = forms.RelationshipAssociationFilterForm
2526
- table = tables.RelationshipAssociationTable
2527
2566
  action_buttons = ()
2528
2567
 
2529
2568
 
2530
- class RelationshipAssociationBulkDeleteView(generic.BulkDeleteView):
2531
- queryset = RelationshipAssociation.objects.all()
2532
- table = tables.RelationshipAssociationTable
2533
- filterset = filters.RelationshipAssociationFilterSet
2534
-
2535
-
2536
- class RelationshipAssociationDeleteView(generic.ObjectDeleteView):
2537
- queryset = RelationshipAssociation.objects.all()
2538
-
2539
-
2540
2569
  #
2541
2570
  # Roles
2542
2571
  #
@@ -3005,63 +3034,42 @@ class StatusUIViewSet(NautobotUIViewSet):
3005
3034
  #
3006
3035
 
3007
3036
 
3008
- class TagListView(generic.ObjectListView):
3009
- queryset = Tag.objects.annotate(items=count_related(TaggedItem, "tag"))
3010
- filterset = filters.TagFilterSet
3011
- filterset_form = forms.TagFilterForm
3012
- table = tables.TagTable
3013
-
3014
-
3015
- class TagView(generic.ObjectView):
3037
+ class TagUIViewSet(NautobotUIViewSet):
3038
+ bulk_update_form_class = forms.TagBulkEditForm
3039
+ filterset_class = filters.TagFilterSet
3040
+ filterset_form_class = forms.TagFilterForm
3041
+ form_class = forms.TagForm
3016
3042
  queryset = Tag.objects.all()
3043
+ serializer_class = serializers.TagSerializer
3044
+ table_class = tables.TagTable
3017
3045
 
3018
- def get_extra_context(self, request, instance):
3019
- tagged_items = (
3020
- TaggedItem.objects.filter(tag=instance).select_related("content_type").prefetch_related("content_object")
3021
- )
3022
-
3023
- # Generate a table of all items tagged with this Tag
3024
- items_table = tables.TaggedItemTable(tagged_items)
3025
- paginate = {
3026
- "paginator_class": EnhancedPaginator,
3027
- "per_page": get_paginate_count(request),
3028
- }
3029
- RequestConfig(request, paginate).configure(items_table)
3030
-
3031
- return {
3032
- "items_count": tagged_items.count(),
3033
- "items_table": items_table,
3034
- "content_types": instance.content_types.order_by("app_label", "model"),
3035
- **super().get_extra_context(request, instance),
3036
- }
3037
-
3038
-
3039
- class TagEditView(generic.ObjectEditView):
3040
- queryset = Tag.objects.all()
3041
- model_form = forms.TagForm
3042
- template_name = "extras/tag_edit.html"
3043
-
3044
-
3045
- class TagDeleteView(generic.ObjectDeleteView):
3046
- queryset = Tag.objects.all()
3047
-
3048
-
3049
- class TagBulkImportView(generic.BulkImportView): # 3.0 TODO: remove, unused
3050
- queryset = Tag.objects.all()
3051
- table = tables.TagTable
3052
-
3046
+ object_detail_content = object_detail.ObjectDetailContent(
3047
+ panels=(
3048
+ object_detail.ObjectFieldsPanel(
3049
+ weight=100,
3050
+ section=SectionChoices.LEFT_HALF,
3051
+ fields="__all__",
3052
+ ),
3053
+ object_detail.ObjectsTablePanel(
3054
+ weight=100,
3055
+ section=SectionChoices.RIGHT_HALF,
3056
+ table_class=tables.TaggedItemTable,
3057
+ table_title="Tagged Objects",
3058
+ table_filter="tag",
3059
+ select_related_fields=["content_type"],
3060
+ prefetch_related_fields=["content_object"],
3061
+ ),
3062
+ ),
3063
+ )
3053
3064
 
3054
- class TagBulkEditView(generic.BulkEditView):
3055
- queryset = Tag.objects.annotate(items=count_related(TaggedItem, "tag"))
3056
- table = tables.TagTable
3057
- form = forms.TagBulkEditForm
3058
- filterset = filters.TagFilterSet
3065
+ def alter_queryset(self, request):
3066
+ queryset = super().alter_queryset(request)
3059
3067
 
3068
+ # Only annotate for list, bulk_edit, bulk_delete views
3069
+ if self.action in ["list", "bulk_update", "bulk_destroy"]:
3070
+ queryset = queryset.annotate(items=count_related(TaggedItem, "tag"))
3060
3071
 
3061
- class TagBulkDeleteView(generic.BulkDeleteView):
3062
- queryset = Tag.objects.annotate(items=count_related(TaggedItem, "tag"))
3063
- table = tables.TagTable
3064
- filterset = filters.TagFilterSet
3072
+ return queryset
3065
3073
 
3066
3074
 
3067
3075
  #
nautobot/ipam/models.py CHANGED
@@ -889,7 +889,7 @@ class Prefix(PrimaryModel):
889
889
  prefix_length__lte=self.prefix_length,
890
890
  network__lte=self.network,
891
891
  broadcast__gte=self.broadcast,
892
- namespace=self.namespace,
892
+ namespace_id=self.namespace_id,
893
893
  )
894
894
 
895
895
  return supernets
@@ -921,7 +921,7 @@ class Prefix(PrimaryModel):
921
921
  ip_version=self.ip_version,
922
922
  network__gte=self.network,
923
923
  broadcast__lte=self.broadcast,
924
- namespace=self.namespace,
924
+ namespace_id=self.namespace_id,
925
925
  )
926
926
 
927
927
  def is_child_node(self):
@@ -1093,6 +1093,17 @@ class Prefix(PrimaryModel):
1093
1093
  For prefixes containing IP addresses and/or pools, pools are considered fully utilized while
1094
1094
  only IP addresses that are not contained within pools are added to the utilization.
1095
1095
 
1096
+ It is recommended that when using this method you add the following prefetch to the queryset when dealing with
1097
+ multiple prefixes to ensure good performance:
1098
+
1099
+ ```
1100
+ prefetch_related(
1101
+ Prefetch(
1102
+ "children", queryset=Prefix.objects.only("network", "prefix_length", "parent_id").order_by()
1103
+ )
1104
+ )
1105
+ ```
1106
+
1096
1107
  Returns:
1097
1108
  UtilizationData (namedtuple): (numerator, denominator)
1098
1109
  """
@@ -1105,7 +1116,7 @@ class Prefix(PrimaryModel):
1105
1116
  # change this when that is the case, see #3873 for historical context.
1106
1117
  if self.type != choices.PrefixTypeChoices.TYPE_CONTAINER:
1107
1118
  pool_ips = IPAddress.objects.filter(
1108
- parent__namespace=self.namespace,
1119
+ parent__namespace_id=self.namespace_id,
1109
1120
  ip_version=self.ip_version,
1110
1121
  host__gte=self.network,
1111
1122
  host__lte=self.broadcast,
@@ -1113,7 +1124,11 @@ class Prefix(PrimaryModel):
1113
1124
  child_ips = netaddr.IPSet(pool_ips)
1114
1125
 
1115
1126
  if self.type != choices.PrefixTypeChoices.TYPE_POOL:
1116
- child_prefixes = netaddr.IPSet(p.prefix for p in self.children.only("network", "prefix_length").iterator())
1127
+ # Using self.children.all over self.children.iterator (with chunk_size given or not) consistently shaves
1128
+ # off around 200 extra SQL queries and shows better performance.
1129
+ # Also note that this is meant to be used in conjunction with a Prefetch on an only query. This query is
1130
+ # performed in nautobot.ipam.tables.PrefixDetailTable.
1131
+ child_prefixes = netaddr.IPSet(p.prefix for p in self.children.all())
1117
1132
 
1118
1133
  numerator_set = child_ips | child_prefixes
1119
1134
 
nautobot/ipam/tables.py CHANGED
@@ -1,5 +1,8 @@
1
+ from django.db.models import Prefetch, QuerySet
1
2
  from django.utils.safestring import mark_safe
2
3
  import django_tables2 as tables
4
+ from django_tables2.data import TableData
5
+ from django_tables2.rows import BoundRows
3
6
  from django_tables2.utils import Accessor
4
7
 
5
8
  from nautobot.core.tables import (
@@ -47,7 +50,9 @@ UTILIZATION_GRAPH = """
47
50
  # object: the base ancestor Prefix, in the case of PrefixDetailTable, else None
48
51
  PREFIX_COPY_LINK = """
49
52
  {% load helpers %}
53
+ {% if not table.hide_hierarchy_ui %}
50
54
  {% tree_hierarchy_ui_representation record.ancestors.count|as_range table.hide_hierarchy_ui base_tree_depth|default:0 %}
55
+ {% endif %}
51
56
  <span class="hover_copy">
52
57
  <a href="\
53
58
  {% if record.present_in_database %}\
@@ -418,6 +423,20 @@ class PrefixDetailTable(PrefixTable):
418
423
  tenant = TenantColumn()
419
424
  tags = TagColumn(url_name="ipam:prefix_list")
420
425
 
426
+ def __init__(self, *args, **kwargs):
427
+ super().__init__(*args, **kwargs)
428
+ # Conditionally prefetch children for the utilization calculation if that column is visible.
429
+ if self.columns["utilization"].visible and isinstance(self.data.data, QuerySet):
430
+ self.data = TableData.from_data(
431
+ self.data.data.prefetch_related(
432
+ Prefetch(
433
+ "children", queryset=Prefix.objects.only("network", "prefix_length", "parent_id").order_by()
434
+ )
435
+ )
436
+ )
437
+ self.data.set_table(self)
438
+ self.rows = BoundRows(data=self.data, table=self, pinned_data=self.pinned_data)
439
+
421
440
  class Meta(PrefixTable.Meta):
422
441
  fields = (
423
442
  "pk",