nautobot 2.3.3__py3-none-any.whl → 2.3.5__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 (333) hide show
  1. nautobot/core/celery/schedulers.py +2 -2
  2. nautobot/core/settings.py +3 -1
  3. nautobot/core/settings.yaml +40 -23
  4. nautobot/core/tests/runner.py +13 -6
  5. nautobot/core/tests/test_settings_schema.py +7 -3
  6. nautobot/core/tests/test_views.py +40 -1
  7. nautobot/core/views/generic.py +15 -15
  8. nautobot/core/views/mixins.py +12 -1
  9. nautobot/core/views/renderers.py +3 -1
  10. nautobot/core/views/utils.py +1 -1
  11. nautobot/dcim/api/serializers.py +1 -0
  12. nautobot/dcim/api/views.py +2 -0
  13. nautobot/dcim/forms.py +1 -1
  14. nautobot/dcim/tables/power.py +1 -1
  15. nautobot/dcim/templates/dcim/devicefamily_retrieve.html +1 -1
  16. nautobot/dcim/tests/test_api.py +58 -4
  17. nautobot/dcim/tests/test_filters.py +1 -1
  18. nautobot/dcim/tests/test_models.py +0 -2
  19. nautobot/dcim/views.py +5 -2
  20. nautobot/extras/api/views.py +9 -0
  21. nautobot/extras/models/jobs.py +9 -1
  22. nautobot/extras/querysets.py +10 -1
  23. nautobot/extras/tables.py +3 -0
  24. nautobot/extras/tests/test_api.py +36 -0
  25. nautobot/extras/tests/test_views.py +76 -1
  26. nautobot/extras/views.py +10 -7
  27. nautobot/ipam/forms.py +6 -1
  28. nautobot/ipam/models.py +5 -11
  29. nautobot/ipam/navigation.py +8 -1
  30. nautobot/ipam/templates/ipam/prefix.html +1 -1
  31. nautobot/ipam/tests/test_filters.py +1 -1
  32. nautobot/ipam/tests/test_views.py +41 -41
  33. nautobot/ipam/views.py +1 -1
  34. nautobot/project-static/docs/404.html +60 -148
  35. nautobot/project-static/docs/additional-features/caching.html +3 -3
  36. nautobot/project-static/docs/additional-features/healthcheck.html +3 -3
  37. nautobot/project-static/docs/apps/index.html +60 -148
  38. nautobot/project-static/docs/apps/nautobot-apps.html +60 -148
  39. nautobot/project-static/docs/assets/javascripts/workers/{search.07f07601.min.js → search.6ce7567c.min.js} +3 -3
  40. nautobot/project-static/docs/assets/javascripts/workers/{search.07f07601.min.js.map → search.6ce7567c.min.js.map} +2 -2
  41. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +60 -148
  42. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +60 -148
  43. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +60 -148
  44. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +60 -148
  45. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +60 -148
  46. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +60 -148
  47. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +60 -148
  48. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +60 -148
  49. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +60 -148
  50. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +60 -148
  51. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +60 -148
  52. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +60 -148
  53. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +60 -148
  54. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +60 -148
  55. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +60 -148
  56. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +60 -148
  57. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +60 -148
  58. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +60 -148
  59. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +60 -148
  60. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +60 -148
  61. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +60 -148
  62. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +60 -148
  63. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +60 -148
  64. nautobot/project-static/docs/configuration/optional-settings.html +3 -3
  65. nautobot/project-static/docs/configuration/required-settings.html +3 -3
  66. nautobot/project-static/docs/development/apps/api/configuration-view.html +60 -148
  67. nautobot/project-static/docs/development/apps/api/database-backend-config.html +60 -148
  68. nautobot/project-static/docs/development/apps/api/models/django-admin.html +60 -148
  69. nautobot/project-static/docs/development/apps/api/models/global-search.html +60 -148
  70. nautobot/project-static/docs/development/apps/api/models/graphql.html +60 -148
  71. nautobot/project-static/docs/development/apps/api/models/index.html +60 -148
  72. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +60 -148
  73. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +60 -148
  74. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +60 -148
  75. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +60 -148
  76. nautobot/project-static/docs/development/apps/api/platform-features/index.html +60 -148
  77. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +60 -148
  78. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +60 -148
  79. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +60 -148
  80. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +60 -148
  81. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +62 -150
  82. nautobot/project-static/docs/development/apps/api/prometheus.html +60 -148
  83. nautobot/project-static/docs/development/apps/api/setup.html +60 -148
  84. nautobot/project-static/docs/development/apps/api/testing.html +61 -149
  85. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +60 -148
  86. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +60 -148
  87. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +60 -148
  88. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +60 -148
  89. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +60 -148
  90. nautobot/project-static/docs/development/apps/api/views/base-template.html +60 -148
  91. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +60 -148
  92. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +60 -148
  93. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +60 -148
  94. nautobot/project-static/docs/development/apps/api/views/index.html +60 -148
  95. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +60 -148
  96. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +60 -148
  97. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +60 -148
  98. nautobot/project-static/docs/development/apps/api/views/notes.html +60 -148
  99. nautobot/project-static/docs/development/apps/api/views/rest-api.html +60 -148
  100. nautobot/project-static/docs/development/apps/api/views/urls.html +60 -148
  101. nautobot/project-static/docs/development/apps/index.html +61 -149
  102. nautobot/project-static/docs/development/apps/migration/code-updates.html +60 -148
  103. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +60 -148
  104. nautobot/project-static/docs/development/apps/migration/from-v1.html +60 -148
  105. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +60 -148
  106. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +60 -148
  107. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +60 -148
  108. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +60 -148
  109. nautobot/project-static/docs/development/apps/porting-from-netbox.html +60 -148
  110. nautobot/project-static/docs/development/core/application-registry.html +60 -148
  111. nautobot/project-static/docs/development/core/best-practices.html +60 -148
  112. nautobot/project-static/docs/development/core/bootstrap-ui.html +60 -148
  113. nautobot/project-static/docs/development/core/caching.html +60 -148
  114. nautobot/project-static/docs/development/core/controllers.html +60 -148
  115. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +60 -148
  116. nautobot/project-static/docs/development/core/generic-views.html +60 -148
  117. nautobot/project-static/docs/development/core/getting-started.html +85 -169
  118. nautobot/project-static/docs/development/core/homepage.html +60 -148
  119. nautobot/project-static/docs/development/core/index.html +60 -148
  120. nautobot/project-static/docs/development/core/model-checklist.html +60 -148
  121. nautobot/project-static/docs/development/core/model-features.html +60 -148
  122. nautobot/project-static/docs/development/core/natural-keys.html +60 -148
  123. nautobot/project-static/docs/development/core/navigation-menu.html +60 -148
  124. nautobot/project-static/docs/development/core/release-checklist.html +60 -148
  125. nautobot/project-static/docs/development/core/role-internals.html +60 -148
  126. nautobot/project-static/docs/development/core/settings.html +60 -148
  127. nautobot/project-static/docs/development/core/style-guide.html +60 -148
  128. nautobot/project-static/docs/development/core/templates.html +60 -148
  129. nautobot/project-static/docs/development/core/testing.html +72 -152
  130. nautobot/project-static/docs/development/core/user-preferences.html +60 -148
  131. nautobot/project-static/docs/development/index.html +60 -148
  132. nautobot/project-static/docs/development/jobs/index.html +68 -156
  133. nautobot/project-static/docs/development/jobs/migration/from-v1.html +61 -149
  134. nautobot/project-static/docs/docker/index.html +3 -3
  135. nautobot/project-static/docs/index.html +60 -148
  136. nautobot/project-static/docs/installation/selinux-troubleshooting.html +3 -3
  137. nautobot/project-static/docs/overview/application_stack.html +60 -148
  138. nautobot/project-static/docs/overview/design_philosophy.html +60 -148
  139. nautobot/project-static/docs/release-notes/index.html +60 -148
  140. nautobot/project-static/docs/release-notes/version-1.0.html +60 -148
  141. nautobot/project-static/docs/release-notes/version-1.1.html +61 -149
  142. nautobot/project-static/docs/release-notes/version-1.2.html +63 -151
  143. nautobot/project-static/docs/release-notes/version-1.3.html +61 -149
  144. nautobot/project-static/docs/release-notes/version-1.4.html +62 -150
  145. nautobot/project-static/docs/release-notes/version-1.5.html +62 -150
  146. nautobot/project-static/docs/release-notes/version-1.6.html +64 -152
  147. nautobot/project-static/docs/release-notes/version-2.0.html +61 -149
  148. nautobot/project-static/docs/release-notes/version-2.1.html +62 -150
  149. nautobot/project-static/docs/release-notes/version-2.2.html +60 -148
  150. nautobot/project-static/docs/release-notes/version-2.3.html +475 -236
  151. nautobot/project-static/docs/search/search_index.json +1 -1
  152. nautobot/project-static/docs/sitemap.xml +277 -285
  153. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  154. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +62 -150
  155. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +61 -149
  156. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +62 -150
  157. nautobot/project-static/docs/user-guide/administration/configuration/index.html +71 -169
  158. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +13 -12524
  159. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +8966 -0
  160. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +13 -9218
  161. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +12734 -0
  162. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +64 -152
  163. nautobot/project-static/docs/user-guide/administration/guides/caching.html +13 -9108
  164. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +61 -149
  165. nautobot/project-static/docs/user-guide/administration/guides/docker.html +9491 -0
  166. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +9478 -0
  167. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +13 -8833
  168. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +64 -152
  169. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +61 -149
  170. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +61 -149
  171. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +60 -148
  172. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +60 -148
  173. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +8978 -0
  174. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +60 -148
  175. nautobot/project-static/docs/user-guide/administration/installation/docker.html +3 -3
  176. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +63 -151
  177. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +3 -3
  178. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +61 -151
  179. nautobot/project-static/docs/user-guide/administration/installation/index.html +62 -150
  180. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +60 -148
  181. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +76 -161
  182. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +3 -3
  183. nautobot/project-static/docs/user-guide/administration/installation/services.html +62 -150
  184. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +13 -9577
  185. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +13 -9560
  186. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +13 -9064
  187. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +62 -150
  188. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +60 -148
  189. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +66 -154
  190. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +63 -151
  191. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +66 -154
  192. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +63 -151
  193. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +63 -151
  194. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +63 -151
  195. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +63 -151
  196. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +63 -151
  197. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +63 -151
  198. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +65 -153
  199. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +63 -151
  200. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +60 -148
  201. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +60 -148
  202. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +60 -148
  203. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +60 -148
  204. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +60 -148
  205. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +60 -148
  206. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +60 -148
  207. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +60 -148
  208. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +60 -148
  209. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +60 -148
  210. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +60 -148
  211. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +60 -148
  212. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +60 -148
  213. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +60 -148
  214. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +60 -148
  215. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +60 -148
  216. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +60 -148
  217. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +60 -148
  218. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +60 -148
  219. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +60 -148
  220. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +60 -148
  221. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +60 -148
  222. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +60 -148
  223. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +60 -148
  224. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +60 -148
  225. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +60 -148
  226. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +60 -148
  227. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +60 -148
  228. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +60 -148
  229. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +60 -148
  230. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +60 -148
  231. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +60 -148
  232. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +60 -148
  233. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +60 -148
  234. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +60 -148
  235. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +60 -148
  236. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +60 -148
  237. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +60 -148
  238. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +61 -149
  239. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +60 -148
  240. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +60 -148
  241. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +60 -148
  242. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +60 -148
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +60 -148
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +60 -148
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +60 -148
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +60 -148
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +60 -148
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +60 -148
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +60 -148
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +60 -148
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +60 -148
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +60 -148
  253. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +61 -149
  254. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +60 -148
  255. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +60 -148
  256. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +60 -148
  257. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +60 -148
  258. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +60 -148
  259. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +60 -148
  260. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +60 -148
  261. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +60 -148
  262. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +60 -148
  263. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +60 -148
  264. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +60 -148
  265. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +60 -148
  266. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +60 -148
  267. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +60 -148
  268. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +60 -148
  269. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +60 -148
  270. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +60 -148
  271. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +60 -148
  272. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +60 -148
  273. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +60 -148
  274. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +60 -148
  275. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +60 -148
  276. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +60 -148
  277. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +60 -148
  278. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +60 -148
  279. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +60 -148
  280. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +60 -148
  281. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +60 -148
  282. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +60 -148
  283. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +60 -148
  284. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +60 -148
  285. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +61 -149
  286. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +60 -148
  287. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +60 -148
  288. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +60 -148
  289. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +60 -148
  290. nautobot/project-static/docs/user-guide/index.html +60 -148
  291. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +60 -148
  292. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +60 -148
  293. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +60 -148
  294. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +60 -148
  295. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +61 -149
  296. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +60 -148
  297. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +60 -148
  298. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +61 -149
  299. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +62 -150
  300. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +60 -148
  301. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +61 -149
  302. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +60 -148
  303. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +60 -148
  304. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +60 -148
  305. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +60 -148
  306. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +60 -148
  307. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +61 -149
  308. nautobot/project-static/docs/user-guide/platform-functionality/note.html +60 -148
  309. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +60 -148
  310. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +60 -148
  311. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +61 -149
  312. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +61 -149
  313. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +62 -150
  314. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +60 -148
  315. nautobot/project-static/docs/user-guide/platform-functionality/role.html +60 -148
  316. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +60 -148
  317. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +60 -148
  318. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +60 -148
  319. nautobot/project-static/docs/user-guide/platform-functionality/status.html +60 -148
  320. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +60 -148
  321. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +60 -148
  322. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +60 -148
  323. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +60 -148
  324. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +60 -148
  325. nautobot/virtualization/filters.py +6 -1
  326. nautobot/virtualization/tables.py +2 -2
  327. {nautobot-2.3.3.dist-info → nautobot-2.3.5.dist-info}/METADATA +2 -2
  328. {nautobot-2.3.3.dist-info → nautobot-2.3.5.dist-info}/RECORD +332 -328
  329. nautobot/project-static/docs/user-guide/administration/configuration/render-settings-fragment.j2 +0 -76
  330. {nautobot-2.3.3.dist-info → nautobot-2.3.5.dist-info}/LICENSE.txt +0 -0
  331. {nautobot-2.3.3.dist-info → nautobot-2.3.5.dist-info}/NOTICE +0 -0
  332. {nautobot-2.3.3.dist-info → nautobot-2.3.5.dist-info}/WHEEL +0 -0
  333. {nautobot-2.3.3.dist-info → nautobot-2.3.5.dist-info}/entry_points.txt +0 -0
nautobot/dcim/views.py CHANGED
@@ -3148,7 +3148,7 @@ class DeviceBayPopulateView(generic.ObjectEditView):
3148
3148
  f"Added {device_bay.installed_device} to {device_bay}.",
3149
3149
  )
3150
3150
 
3151
- return redirect("dcim:device", pk=device_bay.device.pk)
3151
+ return redirect("dcim:device_devicebays", pk=device_bay.device.pk)
3152
3152
 
3153
3153
  return render(
3154
3154
  request,
@@ -3191,7 +3191,7 @@ class DeviceBayDepopulateView(generic.ObjectEditView):
3191
3191
  f"Removed {removed_device} from {device_bay}.",
3192
3192
  )
3193
3193
 
3194
- return redirect("dcim:device", pk=device_bay.device.pk)
3194
+ return redirect("dcim:device_devicebays", pk=device_bay.device.pk)
3195
3195
 
3196
3196
  return render(
3197
3197
  request,
@@ -4139,9 +4139,12 @@ class DeviceFamilyUIViewSet(NautobotUIViewSet):
4139
4139
  context["device_type_table"] = device_type_table
4140
4140
 
4141
4141
  total_devices = 0
4142
+ device_type_count = 0
4142
4143
  for device_type in device_types:
4143
4144
  total_devices += device_type.device_count
4145
+ device_type_count += 1
4144
4146
  context["total_devices"] = total_devices
4147
+ context["device_type_count"] = device_type_count
4145
4148
 
4146
4149
  return context
4147
4150
 
@@ -1,5 +1,6 @@
1
1
  from django.conf import settings
2
2
  from django.contrib.contenttypes.models import ContentType
3
+ from django.db.models import ProtectedError
3
4
  from django.forms import ValidationError as FormsValidationError
4
5
  from django.http import FileResponse, Http404
5
6
  from django.shortcuts import get_object_or_404
@@ -729,6 +730,14 @@ class JobViewSet(
729
730
  ):
730
731
  lookup_value_regex = r"[-0-9a-fA-F]+"
731
732
 
733
+ def perform_destroy(self, obj):
734
+ if obj.module_name.startswith("nautobot."):
735
+ raise ProtectedError(
736
+ f"Unable to delete Job {obj}. System Job cannot be deleted",
737
+ [],
738
+ )
739
+ super().perform_destroy(obj)
740
+
732
741
 
733
742
  @extend_schema_view(
734
743
  destroy=extend_schema(operation_id="extras_jobs_destroy_by_name"),
@@ -11,7 +11,7 @@ from django.contrib.contenttypes.models import ContentType
11
11
  from django.core.exceptions import ValidationError
12
12
  from django.core.validators import MinValueValidator
13
13
  from django.db import models, transaction
14
- from django.db.models import signals
14
+ from django.db.models import ProtectedError, signals
15
15
  from django.utils import timezone
16
16
  from django.utils.functional import cached_property
17
17
  from django_celery_beat.clockedschedule import clocked
@@ -234,6 +234,14 @@ class Job(PrimaryModel):
234
234
  def __str__(self):
235
235
  return self.name
236
236
 
237
+ def delete(self):
238
+ if self.module_name.startswith("nautobot."):
239
+ raise ProtectedError(
240
+ f"Unable to delete Job {self}. System Job cannot be deleted",
241
+ [],
242
+ )
243
+ super().delete()
244
+
237
245
  @property
238
246
  def job_class(self):
239
247
  """
@@ -1,6 +1,6 @@
1
1
  from django.conf import settings
2
2
  from django.contrib.contenttypes.models import ContentType
3
- from django.db.models import F, Model, OuterRef, Q, Subquery
3
+ from django.db.models import F, Model, OuterRef, ProtectedError, Q, Subquery
4
4
  from django.db.models.functions import JSONObject
5
5
 
6
6
  from nautobot.core.models.query_functions import EmptyGroupByJSONBAgg
@@ -224,6 +224,15 @@ class JobQuerySet(RestrictedQuerySet):
224
224
  Extend the standard queryset with a get_for_class_path method.
225
225
  """
226
226
 
227
+ def delete(self):
228
+ for job in self:
229
+ if job.module_name.startswith("nautobot."):
230
+ raise ProtectedError(
231
+ f"Unable to delete Job {job}. System Job cannot be deleted",
232
+ [],
233
+ )
234
+ return super().delete()
235
+
227
236
  def get_for_class_path(self, class_path):
228
237
  try:
229
238
  module_name, job_class_name = class_path.rsplit(".", 1)
nautobot/extras/tables.py CHANGED
@@ -1031,6 +1031,9 @@ class ObjectMetadataTable(BaseTable):
1031
1031
  class NoteTable(BaseTable):
1032
1032
  actions = ButtonsColumn(Note)
1033
1033
  created = tables.LinkColumn()
1034
+ note = tables.Column(
1035
+ attrs={"td": {"class": "rendered-markdown"}},
1036
+ )
1034
1037
 
1035
1038
  class Meta(BaseTable.Meta):
1036
1039
  model = Note
@@ -1388,6 +1388,42 @@ class JobTest(
1388
1388
  job_model = Job.objects.get_for_class_path(class_path)
1389
1389
  return reverse("extras-api:job-run", kwargs={"pk": job_model.pk})
1390
1390
 
1391
+ def get_deletable_object(self):
1392
+ """
1393
+ Get an instance that can be deleted.
1394
+ Exclude system jobs
1395
+ """
1396
+ # filter out the system jobs:
1397
+ queryset = self._get_queryset().exclude(module_name__startswith="nautobot.")
1398
+ instance = get_deletable_objects(self.model, queryset).first()
1399
+ if instance is None:
1400
+ self.fail("Couldn't find a single deletable object!")
1401
+ return instance
1402
+
1403
+ def get_deletable_object_pks(self):
1404
+ """
1405
+ Get a list of PKs corresponding to jobs that can be safely bulk-deleted.
1406
+ Exclude system jobs
1407
+ """
1408
+ queryset = self._get_queryset().exclude(module_name__startswith="nautobot.")
1409
+ instances = get_deletable_objects(self.model, queryset).values_list("pk", flat=True)[:3]
1410
+ if len(instances) < 3:
1411
+ self.fail(f"Couldn't find 3 deletable objects, only found {len(instances)}!")
1412
+ return instances
1413
+
1414
+ def test_delete_system_jobs_fail(self):
1415
+ self.add_permissions("extras.delete_job")
1416
+ instance = self._get_queryset().filter(module_name__startswith="nautobot.").first()
1417
+ job_name = instance.name
1418
+ url = self._get_detail_url(instance)
1419
+ self.client.delete(url, **self.header)
1420
+ # assert Job still exists
1421
+ self.assertTrue(self._get_queryset().filter(name=job_name).exists())
1422
+ self.user.is_superuser = True
1423
+ self.client.delete(url, **self.header)
1424
+ # assert Job still exists
1425
+ self.assertTrue(self._get_queryset().filter(name=job_name).exists())
1426
+
1391
1427
  def test_get_job_variables(self):
1392
1428
  """Test the job/<pk>/variables API endpoint."""
1393
1429
  self.add_permissions("extras.view_job")
@@ -18,7 +18,7 @@ from nautobot.core.choices import ColorChoices
18
18
  from nautobot.core.models.fields import slugify_dashes_to_underscores
19
19
  from nautobot.core.templatetags.helpers import bettertitle
20
20
  from nautobot.core.testing import extract_form_failures, extract_page_body, ModelViewTestCase, TestCase, ViewTestCases
21
- from nautobot.core.testing.utils import disable_warnings, post_data
21
+ from nautobot.core.testing.utils import disable_warnings, get_deletable_objects, post_data
22
22
  from nautobot.core.utils.permissions import get_permission_for_model
23
23
  from nautobot.dcim.models import (
24
24
  ConsolePort,
@@ -1840,6 +1840,9 @@ class ApprovalQueueTestCase(
1840
1840
  return reverse("extras:scheduledjob_approval_request_view", kwargs={"pk": instance.pk})
1841
1841
  raise ValueError("This override is only valid for list and view test cases")
1842
1842
 
1843
+ def get_list_url(self):
1844
+ return reverse("extras:scheduledjob_approval_queue_list")
1845
+
1843
1846
  def setUp(self):
1844
1847
  super().setUp()
1845
1848
  self.job_model = Job.objects.get_for_class_path("dry_run.TestDryRun")
@@ -2363,6 +2366,78 @@ class JobTestCase(
2363
2366
  "clear_task_queues_override": False,
2364
2367
  }
2365
2368
 
2369
+ def get_deletable_object(self):
2370
+ """
2371
+ Get an instance that can be deleted.
2372
+ Exclude system jobs
2373
+ """
2374
+ # filter out the system jobs:
2375
+ queryset = self._get_queryset().exclude(module_name__startswith="nautobot.")
2376
+ return get_deletable_objects(self.model, queryset).first()
2377
+
2378
+ def get_deletable_object_pks(self):
2379
+ """
2380
+ Get a list of PKs corresponding to jobs that can be safely bulk-deleted.
2381
+ Excluding system jobs
2382
+ """
2383
+ queryset = self._get_queryset().exclude(module_name__startswith="nautobot.")
2384
+ return get_deletable_objects(self.model, queryset).values_list("pk", flat=True)[:3]
2385
+
2386
+ def test_delete_system_jobs_fail(self):
2387
+ instance = self._get_queryset().filter(module_name__startswith="nautobot.").first()
2388
+ job_name = instance.name
2389
+ request = {
2390
+ "path": self._get_url("delete", instance),
2391
+ "data": post_data({"confirm": True}),
2392
+ }
2393
+
2394
+ # Try delete with delete job permission
2395
+ self.add_permissions("extras.delete_job")
2396
+ response = self.client.post(**request, follow=True)
2397
+ self.assertHttpStatus(response, 403)
2398
+ response_body = extract_page_body(response.content.decode(response.charset))
2399
+ self.assertIn(f"Unable to delete Job {instance}. System Job cannot be deleted", response_body)
2400
+ # assert Job still exists
2401
+ self.assertTrue(self._get_queryset().filter(name=job_name).exists())
2402
+
2403
+ # Try delete as a superuser
2404
+ self.user.is_superuser = True
2405
+ response = self.client.post(**request, follow=True)
2406
+ self.assertHttpStatus(response, 403)
2407
+ response_body = extract_page_body(response.content.decode(response.charset))
2408
+ self.assertIn(f"Unable to delete Job {instance}. System Job cannot be deleted", response_body)
2409
+ # assert Job still exists
2410
+ self.assertTrue(self._get_queryset().filter(name=job_name).exists())
2411
+
2412
+ def test_bulk_delete_system_jobs_fail(self):
2413
+ system_job_queryset = self.model.objects.filter(module_name__startswith="nautobot.")
2414
+ pk_list = system_job_queryset.values_list("pk", flat=True)[:3]
2415
+ initial_count = self._get_queryset().count()
2416
+ data = {
2417
+ "pk": pk_list,
2418
+ "confirm": True,
2419
+ "_confirm": True, # Form button
2420
+ }
2421
+ # Try bulk delete with delete job permission
2422
+ self.add_permissions("extras.delete_job")
2423
+ response = self.client.post(self._get_url("bulk_delete"), data, follow=True)
2424
+ self.assertHttpStatus(response, 403)
2425
+ self.assertEqual(self._get_queryset().count(), initial_count)
2426
+ response_body = extract_page_body(response.content.decode(response.charset))
2427
+ self.assertIn(
2428
+ f"Unable to delete Job {system_job_queryset.first()}. System Job cannot be deleted", response_body
2429
+ )
2430
+
2431
+ # Try bulk delete as a superuser
2432
+ self.user.is_superuser = True
2433
+ response = self.client.post(self._get_url("bulk_delete"), data, follow=True)
2434
+ self.assertHttpStatus(response, 403)
2435
+ self.assertEqual(self._get_queryset().count(), initial_count)
2436
+ response_body = extract_page_body(response.content.decode(response.charset))
2437
+ self.assertIn(
2438
+ f"Unable to delete Job {system_job_queryset.first()}. System Job cannot be deleted", response_body
2439
+ )
2440
+
2366
2441
  def validate_job_data_after_bulk_edit(self, pk_list, old_data):
2367
2442
  # Name is bulk-editable
2368
2443
  overridable_fields = [field for field in JOB_OVERRIDABLE_FIELDS if field != "name"]
nautobot/extras/views.py CHANGED
@@ -4,7 +4,6 @@ from urllib.parse import parse_qs
4
4
  from celery import chain
5
5
  from django.conf import settings
6
6
  from django.contrib import messages
7
- from django.contrib.auth.models import AnonymousUser
8
7
  from django.contrib.contenttypes.models import ContentType
9
8
  from django.core.exceptions import ObjectDoesNotExist, ValidationError
10
9
  from django.db import IntegrityError, transaction
@@ -23,6 +22,7 @@ from django.views.generic import View
23
22
  from django_tables2 import RequestConfig
24
23
  from jsonschema.validators import Draft7Validator
25
24
  from rest_framework.decorators import action
25
+ from rest_framework.permissions import IsAuthenticated
26
26
 
27
27
  try:
28
28
  from zoneinfo import ZoneInfo
@@ -1650,6 +1650,9 @@ class SavedViewUIViewSet(
1650
1650
  serializer_class = serializers.SavedViewSerializer
1651
1651
  table_class = tables.SavedViewTable
1652
1652
  action_buttons = ("export",)
1653
+ permission_classes = [
1654
+ IsAuthenticated,
1655
+ ]
1653
1656
 
1654
1657
  def alter_queryset(self, request):
1655
1658
  """
@@ -1676,15 +1679,15 @@ class SavedViewUIViewSet(
1676
1679
 
1677
1680
  def check_permissions(self, request):
1678
1681
  """
1679
- Override this method to not check any permissions.
1682
+ Override this method to not check any nautobot-specific object permissions and to only check if the user is authenticated.
1680
1683
  Since users with <app_label>.view_<model_name> permissions should be able to view saved views related to this model.
1681
1684
  And those permissions will be enforced in the related view.
1682
1685
  """
1683
-
1684
- def dispatch(self, request, *args, **kwargs):
1685
- if isinstance(request.user, AnonymousUser):
1686
- return self.handle_no_permission()
1687
- return super().dispatch(request, *args, **kwargs)
1686
+ for permission in self.get_permissions():
1687
+ if not permission.has_permission(request, self):
1688
+ self.permission_denied(
1689
+ request, message=getattr(permission, "message", None), code=getattr(permission, "code", None)
1690
+ )
1688
1691
 
1689
1692
  def extra_message_context(self, obj):
1690
1693
  """
nautobot/ipam/forms.py CHANGED
@@ -873,6 +873,12 @@ class ServiceForm(NautobotModelForm):
873
873
  base_field=forms.IntegerField(min_value=SERVICE_PORT_MIN, max_value=SERVICE_PORT_MAX),
874
874
  help_text="Comma-separated list of one or more port numbers. A range may be specified using a hyphen.",
875
875
  )
876
+ ip_addresses = DynamicModelMultipleChoiceField(
877
+ queryset=IPAddress.objects.all(),
878
+ required=False,
879
+ label="IP addresses",
880
+ query_params={"device_id": "$device", "virtual_machine_id": "$virtual_machine"},
881
+ )
876
882
 
877
883
  class Meta:
878
884
  model = Service
@@ -892,7 +898,6 @@ class ServiceForm(NautobotModelForm):
892
898
  }
893
899
  widgets = {
894
900
  "protocol": StaticSelect2(),
895
- "ip_addresses": StaticSelect2Multiple(),
896
901
  }
897
902
 
898
903
  def __init__(self, *args, **kwargs):
nautobot/ipam/models.py CHANGED
@@ -889,22 +889,16 @@ class Prefix(PrimaryModel):
889
889
  )
890
890
  return available_ips
891
891
 
892
- def get_child_ips(self):
892
+ def get_all_ips(self):
893
893
  """
894
- Return IP addresses with this prefix as parent.
895
-
896
- In a future release, if this prefix is a pool, it will return IP addresses within the pool's address space.
894
+ Return all IP addresses contained within this prefix, including child prefixes' IP addresses.
897
895
 
898
896
  Returns:
899
897
  IPAddress QuerySet
900
898
  """
901
- # 3.0 TODO: uncomment this to enable this logic
902
- # if self.type == choices.PrefixTypeChoices.TYPE_POOL:
903
- # return IPAddress.objects.filter(
904
- # parent__namespace=self.namespace, host__gte=self.network, host__lte=self.broadcast
905
- # )
906
- # else:
907
- return self.ip_addresses.all()
899
+ return IPAddress.objects.filter(
900
+ parent__namespace=self.namespace, host__gte=self.network, host__lte=self.broadcast
901
+ )
908
902
 
909
903
  def get_first_available_prefix(self):
910
904
  """
@@ -191,7 +191,14 @@ menu_items = (
191
191
  permissions=[
192
192
  "ipam.view_service",
193
193
  ],
194
- buttons=(),
194
+ buttons=(
195
+ NavMenuAddButton(
196
+ link="ipam:service_add",
197
+ permissions=[
198
+ "ipam.add_service",
199
+ ],
200
+ ),
201
+ ),
195
202
  ),
196
203
  ),
197
204
  ),
@@ -33,7 +33,7 @@
33
33
  </li>
34
34
  {% if perms.ipam.view_ipaddress %}
35
35
  <li role="presentation"{% if active_tab == 'ip-addresses' %} class="active"{% endif %}>
36
- <a href="{% url 'ipam:prefix_ipaddresses' pk=object.pk %}">IP Addresses <span class="badge">{{ object.get_child_ips.count }}</span></a>
36
+ <a href="{% url 'ipam:prefix_ipaddresses' pk=object.pk %}">IP Addresses <span class="badge">{{ object.get_all_ips.count }}</span></a>
37
37
  </li>
38
38
  {% endif %}
39
39
  {% endblock extra_nav_tabs %}
@@ -1256,7 +1256,7 @@ class VLANLocationAssignmentTestCase(FilterTestCases.FilterTestCase):
1256
1256
  params = {"q": vlan_vid}
1257
1257
  queryset = VLANLocationAssignment.objects.exclude(location__name__icontains=vlan_vid)
1258
1258
  filterset = VLANLocationAssignmentFilterSet(params, queryset).qs
1259
- expected_queryset = VLANLocationAssignment.objects.filter(vlan__vid__exact=vlan_vid)
1259
+ expected_queryset = queryset.filter(vlan__vid__exact=vlan_vid)
1260
1260
  self.assertQuerysetEqualAndNotEmpty(filterset, expected_queryset)
1261
1261
 
1262
1262
 
@@ -328,6 +328,44 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase, ViewTestCases.List
328
328
  strip_tags(content),
329
329
  )
330
330
 
331
+ @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
332
+ def test_prefix_ipaddresses_table_list_includes_child_ips(self):
333
+ ip_status = Status.objects.get_for_model(IPAddress).first()
334
+ instance = Prefix.objects.create(
335
+ prefix="5.5.10.0/23",
336
+ namespace=self.namespace,
337
+ type=PrefixTypeChoices.TYPE_NETWORK,
338
+ status=self.statuses[1],
339
+ )
340
+ Prefix.objects.create(
341
+ prefix="5.5.10.0/30",
342
+ namespace=self.namespace,
343
+ type=PrefixTypeChoices.TYPE_POOL,
344
+ status=self.statuses[1],
345
+ )
346
+ IPAddress.objects.create(
347
+ address="5.5.10.1/23",
348
+ status=ip_status,
349
+ namespace=self.namespace,
350
+ )
351
+ IPAddress.objects.create(
352
+ address="5.5.10.4/23",
353
+ status=ip_status,
354
+ namespace=self.namespace,
355
+ )
356
+ url = reverse("ipam:prefix_ipaddresses", args=(instance.pk,))
357
+ response = self.client.get(url)
358
+ self.assertHttpStatus(response, 200)
359
+ content = response.content.decode(response.charset)
360
+ # This validates that both parent prefix and child prefix IPAddresses are present in parent prefix IPAddresses list
361
+ self.assertIn("5.5.10.1/23", strip_tags(content))
362
+ self.assertIn("5.5.10.4/23", strip_tags(content))
363
+ print(response.content.decode(response.charset))
364
+ ip_address_tab = (
365
+ f'<li role="presentation" class="active"><a href="{url}">IP Addresses <span class="badge">2</span></a></li>'
366
+ )
367
+ self.assertInHTML(ip_address_tab, content)
368
+
331
369
 
332
370
  class IPAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
333
371
  model = IPAddress
@@ -1005,7 +1043,6 @@ class VLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1005
1043
  @classmethod
1006
1044
  def setUpTestData(cls):
1007
1045
  cls.locations = Location.objects.filter(location_type=LocationType.objects.get(name="Campus"))
1008
- location_1 = cls.locations.first()
1009
1046
 
1010
1047
  vlangroups = (
1011
1048
  VLANGroup.objects.create(name="VLAN Group 1", location=cls.locations.first()),
@@ -1014,51 +1051,14 @@ class VLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1014
1051
 
1015
1052
  roles = Role.objects.get_for_model(VLAN)[:2]
1016
1053
 
1017
- statuses = Status.objects.get_for_model(VLAN)
1018
- status_1 = statuses[0]
1019
- status_2 = statuses[1]
1020
-
1021
- vlans = (
1022
- VLAN.objects.create(
1023
- vlan_group=vlangroups[0],
1024
- vid=101,
1025
- name="VLAN101",
1026
- role=roles[0],
1027
- status=status_1,
1028
- _custom_field_data={"custom_field": "Value"},
1029
- ),
1030
- VLAN.objects.create(
1031
- vlan_group=vlangroups[0],
1032
- vid=102,
1033
- name="VLAN102",
1034
- role=roles[0],
1035
- status=status_1,
1036
- _custom_field_data={"custom_field": "Value"},
1037
- ),
1038
- VLAN.objects.create(
1039
- vlan_group=vlangroups[0],
1040
- vid=103,
1041
- name="VLAN103",
1042
- role=roles[0],
1043
- status=status_1,
1044
- _custom_field_data={"custom_field": "Value"},
1045
- ),
1046
- )
1047
- vlans[0].locations.add(location_1)
1048
- vlans[1].locations.add(location_1)
1049
- vlans[2].locations.add(location_1)
1050
-
1051
- custom_field = CustomField.objects.create(
1052
- type=CustomFieldTypeChoices.TYPE_TEXT, label="Custom Field", default=""
1053
- )
1054
- custom_field.content_types.set([ContentType.objects.get_for_model(VLAN)])
1054
+ status = Status.objects.get_for_model(VLAN).first()
1055
1055
 
1056
1056
  cls.form_data = {
1057
1057
  "vlan_group": vlangroups[1].pk,
1058
1058
  "vid": 999,
1059
1059
  "name": "VLAN999 with an unwieldy long name since we increased the limit to more than 64 characters",
1060
1060
  "tenant": None,
1061
- "status": status_2.pk,
1061
+ "status": status.pk,
1062
1062
  "role": roles[1].pk,
1063
1063
  "locations": list(cls.locations.values_list("pk", flat=True)[:2]),
1064
1064
  "description": "A new VLAN",
@@ -1068,7 +1068,7 @@ class VLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1068
1068
  cls.bulk_edit_data = {
1069
1069
  "vlan_group": vlangroups[0].pk,
1070
1070
  "tenant": Tenant.objects.first().pk,
1071
- "status": status_2.pk,
1071
+ "status": status.pk,
1072
1072
  "role": roles[0].pk,
1073
1073
  "description": "New description",
1074
1074
  }
nautobot/ipam/views.py CHANGED
@@ -522,7 +522,7 @@ class PrefixIPAddressesView(generic.ObjectView):
522
522
  def get_extra_context(self, request, instance):
523
523
  # Find all IPAddresses belonging to this Prefix
524
524
  ipaddresses = (
525
- instance.ip_addresses.all()
525
+ instance.get_all_ips()
526
526
  .restrict(request.user, "view")
527
527
  .select_related("role", "status", "tenant")
528
528
  .prefetch_related("primary_ip4_for", "primary_ip6_for")