nautobot 2.3.0__py3-none-any.whl → 2.3.0b1__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 (366) hide show
  1. nautobot/cloud/factory.py +0 -2
  2. nautobot/cloud/filters.py +0 -3
  3. nautobot/cloud/forms.py +1 -7
  4. nautobot/cloud/migrations/0001_initial.py +1 -1
  5. nautobot/cloud/models.py +2 -1
  6. nautobot/cloud/tables.py +17 -1
  7. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +7 -1
  8. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -11
  9. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -4
  10. nautobot/cloud/tests/test_filters.py +0 -12
  11. nautobot/core/filters.py +1 -15
  12. nautobot/core/forms/forms.py +2 -10
  13. nautobot/core/graphql/generators.py +2 -2
  14. nautobot/core/graphql/schema.py +14 -6
  15. nautobot/core/jobs/__init__.py +1 -4
  16. nautobot/core/management/commands/generate_test_data.py +2 -2
  17. nautobot/core/models/__init__.py +2 -2
  18. nautobot/core/settings.py +2 -13
  19. nautobot/core/settings.yaml +2 -16
  20. nautobot/core/tables.py +0 -3
  21. nautobot/core/templates/generic/object_retrieve.html +5 -5
  22. nautobot/core/templates/nautobot_config.py.j2 +0 -15
  23. nautobot/core/testing/filters.py +1 -12
  24. nautobot/core/tests/integration/test_general_functionality.py +1 -1
  25. nautobot/core/tests/test_jobs.py +1 -74
  26. nautobot/core/views/generic.py +1 -1
  27. nautobot/core/views/mixins.py +1 -1
  28. nautobot/core/views/utils.py +6 -8
  29. nautobot/dcim/factory.py +1 -4
  30. nautobot/dcim/filters/__init__.py +0 -4
  31. nautobot/dcim/forms.py +0 -5
  32. nautobot/dcim/migrations/0061_module_models.py +0 -1
  33. nautobot/dcim/models/device_components.py +0 -7
  34. nautobot/dcim/models/devices.py +4 -6
  35. nautobot/dcim/models/racks.py +1 -0
  36. nautobot/dcim/tables/devices.py +3 -17
  37. nautobot/dcim/tables/devicetypes.py +1 -1
  38. nautobot/dcim/templates/dcim/device/base.html +1 -1
  39. nautobot/dcim/templates/dcim/device.html +2 -2
  40. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -6
  41. nautobot/dcim/templates/dcim/moduletype_retrieve.html +0 -17
  42. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +2 -2
  43. nautobot/dcim/tests/test_api.py +0 -2
  44. nautobot/dcim/tests/test_filters.py +7 -14
  45. nautobot/dcim/tests/test_models.py +0 -31
  46. nautobot/dcim/tests/test_views.py +0 -39
  47. nautobot/dcim/views.py +1 -4
  48. nautobot/extras/api/views.py +59 -7
  49. nautobot/extras/factory.py +12 -50
  50. nautobot/extras/forms/base.py +4 -10
  51. nautobot/extras/homepage.py +2 -12
  52. nautobot/extras/jobs.py +2 -2
  53. nautobot/extras/migrations/0111_metadata.py +4 -4
  54. nautobot/extras/models/jobs.py +0 -83
  55. nautobot/extras/models/metadata.py +18 -18
  56. nautobot/extras/models/models.py +0 -2
  57. nautobot/extras/signals.py +1 -14
  58. nautobot/extras/tables.py +14 -43
  59. nautobot/extras/templates/extras/job_detail.html +0 -11
  60. nautobot/extras/tests/test_api.py +9 -16
  61. nautobot/extras/tests/test_jobs.py +2 -2
  62. nautobot/extras/tests/test_models.py +18 -20
  63. nautobot/extras/tests/test_views.py +3 -23
  64. nautobot/extras/utils.py +6 -35
  65. nautobot/extras/views.py +50 -27
  66. nautobot/ipam/filters.py +1 -1
  67. nautobot/ipam/forms.py +1 -1
  68. nautobot/ipam/models.py +20 -9
  69. nautobot/ipam/tables.py +0 -4
  70. nautobot/ipam/tests/test_models.py +2 -3
  71. nautobot/ipam/views.py +11 -6
  72. nautobot/project-static/css/base.css +0 -1
  73. nautobot/project-static/docs/404.html +18 -18
  74. nautobot/project-static/docs/apps/index.html +18 -18
  75. nautobot/project-static/docs/apps/nautobot-apps.html +18 -18
  76. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +1 -0
  77. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +1 -0
  78. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +18 -18
  79. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +18 -18
  80. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +18 -66
  81. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +18 -18
  82. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +18 -18
  83. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +18 -18
  84. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +18 -18
  85. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +18 -18
  86. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +18 -66
  87. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +18 -34
  88. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +18 -82
  89. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +21 -75
  90. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +18 -18
  91. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +18 -34
  92. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +18 -34
  93. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +18 -18
  94. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +18 -18
  95. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +18 -18
  96. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +18 -18
  97. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +18 -18
  98. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +18 -18
  99. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +19 -21
  100. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +18 -34
  101. nautobot/project-static/docs/development/apps/api/configuration-view.html +18 -18
  102. nautobot/project-static/docs/development/apps/api/database-backend-config.html +18 -18
  103. nautobot/project-static/docs/development/apps/api/models/django-admin.html +18 -18
  104. nautobot/project-static/docs/development/apps/api/models/global-search.html +18 -18
  105. nautobot/project-static/docs/development/apps/api/models/graphql.html +18 -18
  106. nautobot/project-static/docs/development/apps/api/models/index.html +22 -33
  107. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +18 -18
  108. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +18 -18
  109. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +18 -18
  110. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +18 -18
  111. nautobot/project-static/docs/development/apps/api/platform-features/index.html +18 -18
  112. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +18 -18
  113. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +18 -18
  114. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +18 -18
  115. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +18 -18
  116. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +18 -18
  117. nautobot/project-static/docs/development/apps/api/prometheus.html +18 -18
  118. nautobot/project-static/docs/development/apps/api/setup.html +18 -18
  119. nautobot/project-static/docs/development/apps/api/testing.html +18 -18
  120. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +18 -18
  121. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +18 -18
  122. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +18 -18
  123. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +18 -18
  124. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +18 -18
  125. nautobot/project-static/docs/development/apps/api/views/base-template.html +18 -18
  126. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +18 -18
  127. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +18 -18
  128. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +18 -18
  129. nautobot/project-static/docs/development/apps/api/views/index.html +18 -18
  130. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +18 -18
  131. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +18 -18
  132. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +18 -18
  133. nautobot/project-static/docs/development/apps/api/views/notes.html +18 -18
  134. nautobot/project-static/docs/development/apps/api/views/rest-api.html +18 -18
  135. nautobot/project-static/docs/development/apps/api/views/urls.html +18 -18
  136. nautobot/project-static/docs/development/apps/index.html +18 -18
  137. nautobot/project-static/docs/development/apps/migration/code-updates.html +18 -18
  138. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +18 -18
  139. nautobot/project-static/docs/development/apps/migration/from-v1.html +18 -18
  140. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +18 -18
  141. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +18 -18
  142. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +18 -18
  143. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +18 -18
  144. nautobot/project-static/docs/development/apps/porting-from-netbox.html +18 -18
  145. nautobot/project-static/docs/development/core/application-registry.html +18 -18
  146. nautobot/project-static/docs/development/core/best-practices.html +18 -18
  147. nautobot/project-static/docs/development/core/bootstrap-ui.html +18 -18
  148. nautobot/project-static/docs/development/core/caching.html +18 -18
  149. nautobot/project-static/docs/development/core/controllers.html +18 -18
  150. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +18 -18
  151. nautobot/project-static/docs/development/core/generic-views.html +18 -18
  152. nautobot/project-static/docs/development/core/getting-started.html +18 -18
  153. nautobot/project-static/docs/development/core/homepage.html +18 -18
  154. nautobot/project-static/docs/development/core/index.html +18 -29
  155. nautobot/project-static/docs/development/core/model-checklist.html +20 -26
  156. nautobot/project-static/docs/development/core/model-features.html +18 -18
  157. nautobot/project-static/docs/development/core/natural-keys.html +18 -18
  158. nautobot/project-static/docs/development/core/navigation-menu.html +18 -18
  159. nautobot/project-static/docs/development/core/release-checklist.html +18 -18
  160. nautobot/project-static/docs/development/core/role-internals.html +18 -18
  161. nautobot/project-static/docs/development/core/settings.html +18 -18
  162. nautobot/project-static/docs/development/core/style-guide.html +19 -19
  163. nautobot/project-static/docs/development/core/templates.html +18 -18
  164. nautobot/project-static/docs/development/core/testing.html +18 -18
  165. nautobot/project-static/docs/development/core/user-preferences.html +18 -18
  166. nautobot/project-static/docs/development/index.html +18 -18
  167. nautobot/project-static/docs/development/jobs/index.html +379 -393
  168. nautobot/project-static/docs/development/jobs/migration/from-v1.html +18 -18
  169. nautobot/project-static/docs/index.html +13 -9032
  170. nautobot/project-static/docs/models/extras/metadatachoice.html +3 -3
  171. nautobot/project-static/docs/models/extras/metadatatype.html +3 -3
  172. nautobot/project-static/docs/models/extras/objectmetadata.html +3 -3
  173. nautobot/project-static/docs/objects.inv +0 -0
  174. nautobot/project-static/docs/overview/application_stack.html +18 -18
  175. nautobot/project-static/docs/overview/design_philosophy.html +20 -20
  176. nautobot/project-static/docs/overview/index.html +9032 -13
  177. nautobot/project-static/docs/release-notes/index.html +19 -252
  178. nautobot/project-static/docs/release-notes/version-1.0.html +18 -18
  179. nautobot/project-static/docs/release-notes/version-1.1.html +18 -18
  180. nautobot/project-static/docs/release-notes/version-1.2.html +18 -18
  181. nautobot/project-static/docs/release-notes/version-1.3.html +18 -18
  182. nautobot/project-static/docs/release-notes/version-1.4.html +18 -18
  183. nautobot/project-static/docs/release-notes/version-1.5.html +18 -18
  184. nautobot/project-static/docs/release-notes/version-1.6.html +18 -18
  185. nautobot/project-static/docs/release-notes/version-2.0.html +18 -18
  186. nautobot/project-static/docs/release-notes/version-2.1.html +18 -18
  187. nautobot/project-static/docs/release-notes/version-2.2.html +111 -248
  188. nautobot/project-static/docs/release-notes/version-2.3.html +90 -520
  189. nautobot/project-static/docs/requirements.txt +3 -3
  190. nautobot/project-static/docs/search/search_index.json +1 -1
  191. nautobot/project-static/docs/sitemap.xml +278 -278
  192. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  193. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +18 -18
  194. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +18 -18
  195. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +18 -18
  196. nautobot/project-static/docs/user-guide/administration/configuration/index.html +18 -18
  197. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +20 -52
  198. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +18 -18
  199. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +18 -18
  200. nautobot/project-static/docs/user-guide/administration/guides/caching.html +18 -18
  201. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +18 -22
  202. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +18 -18
  203. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +18 -18
  204. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +18 -18
  205. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +18 -18
  206. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +18 -18
  207. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +18 -18
  208. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +18 -18
  209. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +18 -18
  210. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +82 -69
  211. nautobot/project-static/docs/user-guide/administration/installation/index.html +24 -24
  212. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +52 -60
  213. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +87 -80
  214. nautobot/project-static/docs/user-guide/administration/installation/services.html +44 -37
  215. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +18 -18
  216. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +18 -18
  217. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +18 -18
  218. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +18 -18
  219. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +18 -18
  220. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +24 -76
  221. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +18 -18
  222. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +18 -18
  223. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +18 -18
  224. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +18 -18
  225. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +18 -18
  226. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +18 -18
  227. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +18 -18
  228. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +18 -18
  229. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +18 -18
  230. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +18 -18
  231. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +18 -18
  232. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +18 -18
  233. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +18 -18
  234. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +18 -18
  235. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +18 -18
  236. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +18 -18
  237. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +18 -18
  238. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +18 -18
  239. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +18 -18
  240. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +18 -18
  241. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +18 -18
  242. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +18 -18
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +18 -18
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +18 -18
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +18 -18
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +18 -18
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +18 -18
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +18 -18
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +18 -18
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +19 -19
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +18 -18
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +18 -18
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +18 -18
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +18 -18
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +18 -18
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +18 -18
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +18 -18
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +18 -18
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +18 -18
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +18 -18
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +18 -18
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +18 -18
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +18 -18
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +19 -19
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +18 -18
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +18 -18
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +18 -18
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +18 -18
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +18 -18
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +18 -18
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +18 -18
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +18 -18
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +18 -18
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +18 -18
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +18 -18
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +18 -18
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +18 -18
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +18 -18
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +18 -18
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +18 -18
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +18 -18
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +18 -18
  283. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +18 -18
  284. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +18 -62
  285. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +18 -18
  286. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +18 -18
  287. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +18 -18
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +18 -18
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +18 -18
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +18 -18
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +18 -18
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +18 -18
  293. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +18 -18
  294. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +18 -18
  295. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +18 -18
  296. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +18 -18
  297. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +18 -18
  298. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +18 -18
  299. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +18 -18
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +18 -18
  301. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +18 -18
  302. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +18 -18
  303. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +18 -18
  304. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +18 -18
  305. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +18 -18
  306. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +18 -18
  307. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +18 -18
  308. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +18 -18
  309. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +18 -18
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +18 -18
  311. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +18 -18
  312. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +18 -18
  313. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +18 -18
  314. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +18 -18
  315. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +18 -18
  316. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +18 -18
  317. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +18 -18
  318. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +18 -18
  319. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +18 -18
  320. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +18 -18
  321. nautobot/project-static/docs/user-guide/index.html +18 -18
  322. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +18 -18
  323. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +18 -18
  324. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +18 -18
  325. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +18 -18
  326. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +18 -18
  327. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +18 -18
  328. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +18 -18
  329. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +18 -18
  330. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +18 -18
  331. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +18 -18
  332. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +18 -18
  333. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +18 -18
  334. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +21 -21
  335. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +18 -18
  336. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +18 -18
  337. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +18 -18
  338. nautobot/project-static/docs/user-guide/platform-functionality/{objectmetadata.html → metadata.html} +84 -197
  339. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +36 -36
  340. nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -33
  341. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +21 -21
  342. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +18 -18
  343. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +18 -18
  344. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +18 -18
  345. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +18 -18
  346. nautobot/project-static/docs/user-guide/platform-functionality/role.html +18 -18
  347. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +18 -18
  348. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +18 -18
  349. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +18 -18
  350. nautobot/project-static/docs/user-guide/platform-functionality/status.html +18 -18
  351. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +18 -18
  352. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +18 -18
  353. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +18 -18
  354. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +18 -18
  355. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +18 -18
  356. nautobot/tenancy/templates/tenancy/tenant.html +4 -4
  357. nautobot/virtualization/models.py +2 -0
  358. nautobot/virtualization/tables.py +5 -2
  359. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/METADATA +3 -3
  360. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/RECORD +364 -364
  361. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +0 -1
  362. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +0 -1
  363. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/LICENSE.txt +0 -0
  364. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/NOTICE +0 -0
  365. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/WHEEL +0 -0
  366. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/entry_points.txt +0 -0
nautobot/cloud/factory.py CHANGED
@@ -24,7 +24,6 @@ class CloudAccountFactory(PrimaryModelFactory):
24
24
  has_description = NautobotBoolIterator()
25
25
  description = factory.Maybe("has_description", factory.Faker("sentence"), "")
26
26
  provider = random_instance(Manufacturer, allow_null=False)
27
- # TODO: once SecretsGroupFactory is implemented:
28
27
  # has_secrets_group = NautobotBoolIterator()
29
28
  # secrets_group = factory.Maybe(
30
29
  # "has_secrets_group",
@@ -41,7 +40,6 @@ class CloudResourceTypeFactory(PrimaryModelFactory):
41
40
  name = factory.LazyAttributeSequence(lambda o, n: f"{o.provider.name} CloudResourceType {n + 1}")
42
41
  has_description = NautobotBoolIterator()
43
42
  description = factory.Maybe("has_description", factory.Faker("sentence"), "")
44
- # TODO: if we add a `config_schema` here, then CloudNetworkFactory and CloudServiceFactory have to follow it...
45
43
 
46
44
  @factory.post_generation
47
45
  def content_types(self, create, extracted, **kwargs):
nautobot/cloud/filters.py CHANGED
@@ -74,8 +74,6 @@ class CloudNetworkFilterSet(NautobotFilterSet):
74
74
  filter_predicates={
75
75
  "name": "icontains",
76
76
  "description": "icontains",
77
- "parent__name": "icontains",
78
- "parent__description": "icontains",
79
77
  "cloud_account__name": "icontains",
80
78
  "cloud_account__description": "icontains",
81
79
  "cloud_resource_type__name": "icontains",
@@ -98,7 +96,6 @@ class CloudNetworkFilterSet(NautobotFilterSet):
98
96
  queryset=models.CloudNetwork.objects.all(),
99
97
  label="Parent cloud network (name or ID)",
100
98
  )
101
- prefixes = django_filters.ModelMultipleChoiceFilter(queryset=Prefix.objects.all())
102
99
 
103
100
  class Meta:
104
101
  model = models.CloudNetwork
nautobot/cloud/forms.py CHANGED
@@ -94,7 +94,6 @@ class CloudNetworkForm(NautobotModelForm):
94
94
  )
95
95
  parent = DynamicModelChoiceField(
96
96
  queryset=CloudNetwork.objects.all(),
97
- query_params={"parent__isnull": True},
98
97
  required=False,
99
98
  )
100
99
  namespace = DynamicModelChoiceField(queryset=Namespace.objects.all(), required=False)
@@ -188,12 +187,7 @@ class CloudNetworkFilterForm(NautobotFilterForm):
188
187
  cloud_account = DynamicModelMultipleChoiceField(
189
188
  queryset=CloudAccount.objects.all(), to_field_name="name", required=False
190
189
  )
191
- parent = DynamicModelMultipleChoiceField(
192
- queryset=CloudNetwork.objects.all(),
193
- query_params={"parent__isnull": True},
194
- to_field_name="name",
195
- required=False,
196
- )
190
+ parent = DynamicModelMultipleChoiceField(queryset=CloudNetwork.objects.all(), to_field_name="name", required=False)
197
191
  tags = TagFilterField(model)
198
192
 
199
193
 
@@ -271,7 +271,7 @@ class Migration(migrations.Migration):
271
271
  field=models.ForeignKey(
272
272
  blank=True,
273
273
  null=True,
274
- on_delete=django.db.models.deletion.PROTECT,
274
+ on_delete=django.db.models.deletion.SET_NULL,
275
275
  related_name="children",
276
276
  to="cloud.cloudnetwork",
277
277
  ),
nautobot/cloud/models.py CHANGED
@@ -14,6 +14,7 @@ from nautobot.extras.utils import FeatureQuery, extras_features
14
14
  @extras_features(
15
15
  "custom_links",
16
16
  "custom_validators",
17
+ "dynamic_groups",
17
18
  "export_templates",
18
19
  "graphql",
19
20
  "webhooks",
@@ -136,7 +137,7 @@ class CloudNetwork(CloudResourceTypeMixin, PrimaryModel):
136
137
  description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
137
138
  cloud_account = models.ForeignKey(to=CloudAccount, on_delete=models.PROTECT, related_name="cloud_networks")
138
139
  parent = models.ForeignKey(
139
- to="cloud.CloudNetwork", on_delete=models.PROTECT, blank=True, null=True, related_name="children"
140
+ to="cloud.CloudNetwork", on_delete=models.SET_NULL, blank=True, null=True, related_name="children"
140
141
  )
141
142
  prefixes = models.ManyToManyField(
142
143
  blank=True,
nautobot/cloud/tables.py CHANGED
@@ -7,8 +7,9 @@ from nautobot.core.tables import (
7
7
  TagColumn,
8
8
  ToggleColumn,
9
9
  )
10
+ from nautobot.tenancy.tables import TenantColumn
10
11
 
11
- from .models import CloudAccount, CloudNetwork, CloudResourceType, CloudService
12
+ from .models import CloudAccount, CloudNetwork, CloudNetworkPrefixAssignment, CloudResourceType, CloudService
12
13
 
13
14
 
14
15
  class CloudAccountTable(BaseTable):
@@ -94,6 +95,21 @@ class CloudNetworkTable(BaseTable):
94
95
  )
95
96
 
96
97
 
98
+ class CloudNetworkPrefixAssignmentTable(BaseTable):
99
+ cloud_network = tables.Column(
100
+ verbose_name="Cloud Network",
101
+ linkify=lambda record: record.cloud_network.get_absolute_url(),
102
+ accessor="cloud_network.name",
103
+ )
104
+ prefix = tables.Column(linkify=True)
105
+ rd = tables.Column(accessor="vrf.rd", verbose_name="RD")
106
+ tenant = TenantColumn(accessor="vrf.tenant")
107
+
108
+ class Meta(BaseTable.Meta):
109
+ model = CloudNetworkPrefixAssignment
110
+ fields = ("cloud_network", "prefix", "rd", "tenant")
111
+
112
+
97
113
  class CloudResourceTypeTable(BaseTable):
98
114
  pk = ToggleColumn()
99
115
  name = tables.Column(linkify=True)
@@ -100,7 +100,13 @@
100
100
  </tr>
101
101
  <tr>
102
102
  <td>Parent</td>
103
- <td>{{ object.parent|hyperlinked_object }}</td>
103
+ <td>
104
+ {% if object.parent %}
105
+ {{ object.parent|hyperlinked_object }}
106
+ {% else %}
107
+ <span class="text-muted">&mdash;</span>
108
+ {% endif %}
109
+ </td>
104
110
  </tr>
105
111
  <tr>
106
112
  <td>Description</td>
@@ -60,17 +60,6 @@
60
60
  </div>
61
61
  {% endblock content_left_page %}
62
62
 
63
- {% block content_right_page %}
64
- <div class="panel panel-default">
65
- <div class="panel-heading">
66
- <strong>Config Schema</strong>
67
- </div>
68
- <div class="panel-body">
69
- <pre>{{ object.config_schema|render_json }}</pre>
70
- </div>
71
- </div>
72
- {% endblock content_right_page %}
73
-
74
63
  {% block extra_tab_content %}
75
64
  {% if networks_count %}
76
65
  <div id="networks" role="tabpanel" class="tab-pane {% if not active_tab and not request.GET.tab or request.GET.tab == "networks" %}active{% else %}fade{% endif %}">
@@ -49,10 +49,6 @@
49
49
  <td>Cloud Resource Type</td>
50
50
  <td>{{ object.cloud_resource_type|hyperlinked_object }}</td>
51
51
  </tr>
52
- <tr>
53
- <td>Description</td>
54
- <td>{{ object.description|placeholder }}</td>
55
- </tr>
56
52
  </table>
57
53
  </div>
58
54
  {% endblock content_left_page %}
@@ -65,18 +65,6 @@ class CloudNetworkTestCase(FilterTestCases.NameOnlyFilterTestCase):
65
65
  ("parent", "parent__id"),
66
66
  ("parent", "parent__name"),
67
67
  ]
68
- exclude_q_filter_predicates = [
69
- "parent__name",
70
- "parent__description",
71
- ]
72
-
73
- def _get_relevant_filterset_queryset(self, queryset, *filter_params):
74
- queryset = super()._get_relevant_filterset_queryset(queryset, *filter_params)
75
- if "name" in filter_params or "description" in filter_params:
76
- # Only select an instance with no children as otherwise the search will also match the children,
77
- # due to `parent__name` and `parent__description` also being search parameters
78
- queryset = queryset.filter(children__isnull=True)
79
- return queryset
80
68
 
81
69
 
82
70
  class CloudNetworkPrefixAssignmentTestCase(FilterTestCases.FilterTestCase):
nautobot/core/filters.py CHANGED
@@ -6,11 +6,9 @@ from django import forms as django_forms
6
6
  from django.conf import settings
7
7
  from django.db import models
8
8
  from django.forms.utils import ErrorDict, ErrorList
9
- from django.utils.encoding import force_str
10
- from django.utils.text import capfirst
11
9
  import django_filters
12
10
  from django_filters.constants import EMPTY_VALUES
13
- from django_filters.utils import get_model_field, label_for_filter, resolve_field, verbose_lookup_expr
11
+ from django_filters.utils import get_model_field, resolve_field
14
12
  from drf_spectacular.types import OpenApiTypes
15
13
  from drf_spectacular.utils import extend_schema_field
16
14
 
@@ -722,18 +720,6 @@ class BaseFilterSet(django_filters.FilterSet):
722
720
  # Of course setting the negation of the existing filter's exclude attribute handles both cases
723
721
  new_filter.exclude = not filter_field.exclude
724
722
 
725
- # If the base filter_field has a custom label, django_filters won't adjust it for the new_filter lookup,
726
- # so we have to do it.
727
- if filter_field.label and filter_field.label != label_for_filter(
728
- cls.Meta.model, filter_field.field_name, filter_field.lookup_expr, filter_field.exclude
729
- ):
730
- # Lightly adjusted from label_for_filter() implementation:
731
- verbose_expression = ["exclude", filter_field.label] if new_filter.exclude else [filter_field.label]
732
- if isinstance(lookup_expr, str):
733
- verbose_expression.append(verbose_lookup_expr(lookup_expr))
734
- verbose_expression = [force_str(part) for part in verbose_expression if part]
735
- new_filter.label = capfirst(" ".join(verbose_expression))
736
-
737
723
  magic_filters[new_filter_name] = new_filter
738
724
 
739
725
  return magic_filters
@@ -59,13 +59,6 @@ class AddressFieldMixin(forms.ModelForm):
59
59
  class BootstrapMixin(forms.BaseForm):
60
60
  """
61
61
  Add the base Bootstrap CSS classes to form elements.
62
-
63
- Note that this only applies to form fields that are:
64
-
65
- 1. statically defined on the form class at declaration time, or
66
- 2. dynamically added to the form at init time by a class **later in the MRO than this mixin**.
67
-
68
- If a class earlier in the MRO adds its own fields, it will have to ensure that the widgets are correctly configured.
69
62
  """
70
63
 
71
64
  def __init__(self, *args, **kwargs):
@@ -80,9 +73,8 @@ class BootstrapMixin(forms.BaseForm):
80
73
 
81
74
  for field in self.fields.values():
82
75
  if field.widget.__class__ not in exempt_widgets:
83
- css_classes = field.widget.attrs.get("class", "")
84
- if "form-control" not in css_classes:
85
- field.widget.attrs["class"] = " ".join([css_classes, "form-control"]).strip()
76
+ css = field.widget.attrs.get("class", "")
77
+ field.widget.attrs["class"] = " ".join([css, "form-control"]).strip()
86
78
  if field.required and not isinstance(field.widget, forms.FileInput):
87
79
  field.widget.attrs["required"] = "required"
88
80
  if "placeholder" not in field.widget.attrs:
@@ -64,8 +64,8 @@ def generate_filter_resolver(schema_type, resolver_name, field_name):
64
64
  """
65
65
  filterset_class = schema_type._meta.filterset_class
66
66
 
67
- def resolve_filter(self, info, **kwargs):
68
- if not filterset_class or not kwargs:
67
+ def resolve_filter(self, *args, **kwargs):
68
+ if not filterset_class:
69
69
  return getattr(self, field_name).all()
70
70
 
71
71
  # Inverse of substitution logic from get_filtering_args_from_filterset() - transform "_type" back to "type"
@@ -4,7 +4,6 @@ from collections import OrderedDict
4
4
  import logging
5
5
 
6
6
  from django.conf import settings
7
- from django.contrib.contenttypes.fields import GenericRelation
8
7
  from django.contrib.contenttypes.models import ContentType
9
8
  from django.core.validators import ValidationError
10
9
  from django.db.models import ManyToManyField
@@ -206,7 +205,8 @@ def extend_schema_type_filter(schema_type, model):
206
205
  (DjangoObjectType): The extended schema_type object
207
206
  """
208
207
  for field in model._meta.get_fields():
209
- if not isinstance(field, (ManyToManyField, ManyToManyRel, ManyToOneRel, GenericRelation)):
208
+ # Check whether attribute is a ManyToOne or ManyToMany field
209
+ if not isinstance(field, (ManyToManyField, ManyToManyRel, ManyToOneRel)):
210
210
  continue
211
211
  # OneToOneRel is a subclass of ManyToOneRel, but we don't want to treat it as a list
212
212
  if isinstance(field, OneToOneRel):
@@ -374,9 +374,16 @@ def extend_schema_type_config_context(schema_type, model):
374
374
 
375
375
  def extend_schema_type_global_features(schema_type, model):
376
376
  """
377
- Extend schema_type object to have attributes and resolvers for global features (dynamic groups, etc.).
377
+ Extend schema_type object to have attributes and resolvers for global features (contacts, dynamic groups, etc.).
378
378
  """
379
- # associated_contacts and associated_object_metadata are handled elsewhere by extend_schema_type_filter()
379
+ if getattr(model, "is_contact_associable_model", False):
380
+
381
+ def resolve_associated_contacts(self, args):
382
+ return self.associated_contacts.all()
383
+
384
+ setattr(schema_type, "resolve_associated_contacts", resolve_associated_contacts)
385
+ schema_type._meta.fields["associated_contacts"] = graphene.Field.mounted(graphene.List(ContactAssociationType))
386
+
380
387
  if getattr(model, "is_dynamic_group_associable_model", False):
381
388
 
382
389
  def resolve_dynamic_groups(self, args):
@@ -392,9 +399,10 @@ def extend_schema_type_relationships(schema_type, model):
392
399
  """Extend the schema type with attributes and resolvers corresponding
393
400
  to the relationships associated with this model."""
394
401
 
402
+ ct = ContentType.objects.get_for_model(model)
395
403
  relationships_by_side = {
396
- "source": Relationship.objects.get_for_model_source(model),
397
- "destination": Relationship.objects.get_for_model_destination(model),
404
+ "source": Relationship.objects.filter(source_type=ct),
405
+ "destination": Relationship.objects.filter(destination_type=ct),
398
406
  }
399
407
 
400
408
  prefix = ""
@@ -1,4 +1,3 @@
1
- import codecs
2
1
  import contextlib
3
2
  from io import BytesIO
4
3
 
@@ -297,9 +296,7 @@ class ImportObjects(Job):
297
296
  if not csv_data and not csv_file:
298
297
  raise RunJobTaskFailed("Either csv_data or csv_file must be provided")
299
298
  if csv_file:
300
- # data_encoding is utf-8 and file_encoding is utf-8-sig
301
- # Bytes read from the original file are decoded according to file_encoding, and the result is encoded using data_encoding.
302
- csv_bytes = codecs.EncodedFile(csv_file, "utf-8", "utf-8-sig")
299
+ csv_bytes = csv_file
303
300
  else:
304
301
  csv_bytes = BytesIO(csv_data.encode("utf-8"))
305
302
 
@@ -329,8 +329,6 @@ class Command(BaseCommand):
329
329
  )
330
330
  _create_batch(MetadataChoiceFactory, 100)
331
331
  _create_batch(ObjectChangeFactory, 100)
332
- _create_batch(JobResultFactory, 20)
333
- _create_batch(JobLogEntryFactory, 100)
334
332
  _create_batch(ObjectMetadataFactory, 100)
335
333
  _create_batch(
336
334
  ObjectMetadataFactory,
@@ -346,6 +344,8 @@ class Command(BaseCommand):
346
344
  has_contact=False,
347
345
  description="with teams",
348
346
  )
347
+ _create_batch(JobResultFactory, 20)
348
+ _create_batch(JobLogEntryFactory, 100)
349
349
 
350
350
  def handle(self, *args, **options):
351
351
  if options["flush"]:
@@ -54,11 +54,11 @@ class BaseModel(models.Model):
54
54
  is_saved_view_model = False # SavedViewMixin overrides this to default True
55
55
  is_cloud_resource_type_model = False # CloudResourceTypeMixin overrides this to default True
56
56
 
57
- associated_object_metadata = GenericRelation(
57
+ associated_object_metadatas = GenericRelation(
58
58
  "extras.ObjectMetadata",
59
59
  content_type_field="assigned_object_type",
60
60
  object_id_field="assigned_object_id",
61
- related_query_name="associated_object_metadata_%(app_label)s_%(class)s", # e.g. 'associated_object_metadata_dcim_device'
61
+ related_query_name="associated_object_metadatas_%(app_label)s_%(class)s", # e.g. 'associated_object_metadatas_dcim_device'
62
62
  )
63
63
 
64
64
  class Meta:
nautobot/core/settings.py CHANGED
@@ -892,24 +892,13 @@ CELERY_TASK_TRACK_STARTED = True
892
892
  # If enabled, a `task-sent` event will be sent for every task so tasks can be tracked before they're consumed by a worker.
893
893
  CELERY_TASK_SEND_SENT_EVENT = True
894
894
 
895
- # How many tasks a worker is allowed to reserve for its own consumption and execution.
896
- # If set to zero (not recommended) a single worker can reserve all tasks even if other workers are free.
897
- # For short running tasks (such as webhooks) you may want to set this to a larger number to increase throughput.
898
- # Conversely, for long running tasks (such as SSoT or Golden-Config Jobs at scale) you may want to set this to 1
899
- # so that a worker executing a long-running task will not prefetch other tasks, which would block their execution
900
- # until the long-running task completes.
901
- # https://docs.celeryq.dev/en/stable/userguide/optimizing.html#prefetch-limits
902
- CELERY_WORKER_PREFETCH_MULTIPLIER = int(os.getenv("NAUTOBOT_CELERY_WORKER_PREFETCH_MULTIPLIER", "4"))
903
-
904
895
  # If enabled stdout and stderr of running jobs will be redirected to the task logger.
905
896
  CELERY_WORKER_REDIRECT_STDOUTS = is_truthy(os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS", "True"))
906
897
 
907
- # The log level of log messages generated by redirected job stdout and stderr.
908
- # Can be one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.
898
+ # The log level of log messages generated by redirected job stdout and stderr. Can be one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.
909
899
  CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS_LEVEL", "WARNING")
910
900
 
911
- # Send task-related events so that tasks can be monitored using tools like flower.
912
- # Sets the default value for the workers -E argument.
901
+ # Send task-related events so that tasks can be monitored using tools like flower. Sets the default value for the workers -E argument.
913
902
  CELERY_WORKER_SEND_TASK_EVENTS = True
914
903
 
915
904
  # Default celery queue name that will be used by workers and tasks if no queue is specified
@@ -426,20 +426,6 @@ properties:
426
426
  see_also:
427
427
  "`CELERY_TASK_SOFT_TIME_LIMIT`": "#celery_task_soft_time_limit"
428
428
  type: "integer"
429
- CELERY_WORKER_PREFETCH_MULTIPLIER:
430
- default: 4
431
- description: "How many tasks a worker is allowed to reserve for its own consumption and execution."
432
- details: >-
433
- If set to `0` (not recommended) a single worker can reserve all tasks even if other workers are free.
434
- For short running tasks (such as webhooks) you may want to set this to a larger number to increase throughput.
435
- Conversely, for long-running tasks (such as SSoT or Golden-Config Jobs at scale) you may want to set this to `1`
436
- so that a worker executing a long-running task will not prefetch other tasks, which would block their execution
437
- until the long-running task completes.
438
- environment_variable: "NAUTOBOT_CELERY_WORKER_PREFETCH_MULTIPLIER"
439
- see_also:
440
- "Celery documentation": "https://docs.celeryq.dev/en/stable/userguide/optimizing.html#prefetch-limits"
441
- type: "integer"
442
- version_added: "2.2.9"
443
429
  CELERY_WORKER_PROMETHEUS_PORTS:
444
430
  default: []
445
431
  description: "Ports for Prometheus metric HTTP server running on the celery worker(s)."
@@ -482,8 +468,8 @@ properties:
482
468
  If enabling indefinite changelog retention, it is recommended to periodically delete old entries.
483
469
  Otherwise, the database may eventually exceed capacity.
484
470
 
485
- +/- 2.3.0
486
- As of Nautobot 2.3.0, changelog cleanup does not run automatically. Use the `Cleanup of ObjectChange records`
471
+ +/- 2.2.0
472
+ As of Nautobot 2.2.0, changelog cleanup does not run automatically. Use the `Cleanup of ObjectChange records`
487
473
  system Job to handle changelog cleanup; you may schedule this to run automatically like any other Job if
488
474
  desired. The `CHANGELOG_RETENTION` setting provides a default age cutoff for the Job but may be overridden
489
475
  at runtime if desired.
nautobot/core/tables.py CHANGED
@@ -155,9 +155,6 @@ class BaseTable(django_tables2.Table):
155
155
  continue
156
156
  if isinstance(column.column, LinkedCountColumn):
157
157
  column_model = lookup.get_model_for_view_name(column.column.viewname)
158
- if column_model is None:
159
- logger.error("Couldn't find model for %s", column.column.viewname)
160
- continue
161
158
  reverse_lookup = column.column.reverse_lookup or next(iter(column.column.url_params.keys()))
162
159
  count_fields.append((column.name, column_model, reverse_lookup))
163
160
  continue
@@ -106,10 +106,10 @@
106
106
  {% endwith %}
107
107
  {% endif %}
108
108
  {% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
109
- {% with object.associated_object_metadata.count as om_count %}
109
+ {% with object.associated_object_metadatas.count as om_count %}
110
110
  {% if om_count %}
111
- <li role="presentation"{% if request.GET.tab == 'object_metadata' %} class="active"{% endif %}>
112
- <a href="{{ object.get_absolute_url }}#object_metadata" onclick="switch_tab(this.href)" aria-controls="object_metadata" role="tab" data-toggle="tab">
111
+ <li role="presentation"{% if request.GET.tab == 'object_metadatas' %} class="active"{% endif %}>
112
+ <a href="{{ object.get_absolute_url }}#object_metadatas" onclick="switch_tab(this.href)" aria-controls="object_metadatas" role="tab" data-toggle="tab">
113
113
  Object Metadata {% badge om_count %}
114
114
  </a>
115
115
  </li>
@@ -246,7 +246,7 @@
246
246
  </div>
247
247
  {% endif %}
248
248
  {% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
249
- <div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
249
+ <div id="object_metadatas" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadatas' %}active{% else %}fade{% endif %}">
250
250
  <div class="row">
251
251
  <div class="col-md-12">
252
252
  <form method="post">
@@ -259,7 +259,7 @@
259
259
  </div>
260
260
  </div>
261
261
  <div class="table-responsive">
262
- {% render_table associated_object_metadata_table 'inc/table.html' %}
262
+ {% render_table associated_object_metadatas_table 'inc/table.html' %}
263
263
  </div>
264
264
  </div>
265
265
  </form>
@@ -295,15 +295,6 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
295
295
  # CELERY_TASK_SOFT_TIME_LIMIT = int(os.getenv("NAUTOBOT_CELERY_TASK_SOFT_TIME_LIMIT", str(5 * 60)))
296
296
  # CELERY_TASK_TIME_LIMIT = int(os.getenv("NAUTOBOT_CELERY_TASK_TIME_LIMIT", str(10 * 60)))
297
297
 
298
- # How many tasks a worker is allowed to reserve for its own consumption and execution.
299
- # If set to zero (not recommended) a single worker can reserve all tasks even if other workers are free.
300
- # For short running tasks (such as webhooks) you may want to set this to a larger number to increase throughput.
301
- # Conversely, for long running tasks (such as SSoT or Golden-Config Jobs at scale) you may want to set this to 1
302
- # so that a worker executing a long-running task will not prefetch other tasks, which would block their execution
303
- # until the long-running task completes.
304
- # https://docs.celeryq.dev/en/stable/userguide/optimizing.html#prefetch-limits
305
- # CELERY_WORKER_PREFETCH_MULTIPLIER = int(os.getenv("NAUTOBOT_CELERY_WORKER_PREFETCH_MULTIPLIER", "4"))
306
-
307
298
  # Ports for prometheus metric HTTP server running on the celery worker.
308
299
  # Normally this should be set to a single port, unless you have multiple workers running on a single machine, i.e.
309
300
  # sharing the same available ports. In that case you need to specify a range of ports greater than or equal to the
@@ -316,12 +307,6 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
316
307
  # int(value) for value in os.getenv("NAUTOBOT_CELERY_WORKER_PROMETHEUS_PORTS").split(",")
317
308
  # ]
318
309
 
319
- # If enabled stdout and stderr of running jobs will be redirected to the task logger.
320
- # CELERY_WORKER_REDIRECT_STDOUTS = is_truthy(os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS", "True"))
321
-
322
- # The log level of log messages generated by redirected job stdout and stderr.
323
- # Can be one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.
324
- # CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS_LEVEL", "WARNING")
325
310
 
326
311
  # Number of days to retain changelog entries. Set to 0 to retain changes indefinitely. Defaults to 90 if not set here.
327
312
  #
@@ -132,17 +132,6 @@ class FilterTestCases:
132
132
  if generic_filter_test not in self.generic_filter_tests:
133
133
  self.generic_filter_tests = (*self.generic_filter_tests, generic_filter_test)
134
134
 
135
- # Make sure we have at least 3 contacts and 3 teams in the database
136
- if Contact.objects.count() < 3:
137
- Contact.objects.create(name="Generic Filter Test Contact 1")
138
- Contact.objects.create(name="Generic Filter Test Contact 2")
139
- Contact.objects.create(name="Generic Filter Test Contact 3")
140
-
141
- if Team.objects.count() < 3:
142
- Team.objects.create(name="Generic Filter Test Team 1")
143
- Team.objects.create(name="Generic Filter Test Team 2")
144
- Team.objects.create(name="Generic Filter Test Team 3")
145
-
146
135
  # Make sure we have some valid contact-associations:
147
136
  for contact, team, instance in zip(Contact.objects.all()[:3], Team.objects.all()[:3], self.queryset):
148
137
  ContactAssociation.objects.create(
@@ -283,7 +272,7 @@ class FilterTestCases:
283
272
  # if lookup_method is iexact use the full updated attr
284
273
  if lookup_method == "iexact":
285
274
  lookup = randomized_attr_value.upper()
286
- model_queryset = self.queryset.filter(**{f"{filter_field_name}__iexact": lookup})
275
+ model_queryset = self.queryset.filter(**{f"{filter_field_name}": lookup})
287
276
  else:
288
277
  lookup = randomized_attr_value[1:].upper()
289
278
  model_queryset = self.queryset.filter(**{f"{filter_field_name}__icontains": lookup})
@@ -24,7 +24,7 @@ class StaticMediaFailureTestCase(SeleniumTestCase):
24
24
  reverse("graphql"),
25
25
  reverse("api_docs"),
26
26
  "/admin/",
27
- "/static/docs/index.html",
27
+ "/static/docs/overview/index.html",
28
28
  ]
29
29
  for url in test_urls:
30
30
  with self.subTest(test_url=url):
@@ -3,27 +3,24 @@ from pathlib import Path
3
3
 
4
4
  from django.contrib.contenttypes.models import ContentType
5
5
  from django.core.cache import cache
6
- from django.core.files.base import ContentFile
7
6
  from django.utils import timezone
8
7
  import yaml
9
8
 
10
9
  from nautobot.core.jobs.cleanup import CleanupTypes
11
10
  from nautobot.core.testing import create_job_result_and_run_job, TransactionTestCase
12
- from nautobot.dcim.models import Device, DeviceType, Location, LocationType, Manufacturer
11
+ from nautobot.dcim.models import DeviceType, Location, LocationType, Manufacturer
13
12
  from nautobot.extras.choices import JobResultStatusChoices, LogLevelChoices
14
13
  from nautobot.extras.factory import JobResultFactory, ObjectChangeFactory
15
14
  from nautobot.extras.models import (
16
15
  Contact,
17
16
  ContactAssociation,
18
17
  ExportTemplate,
19
- FileProxy,
20
18
  JobLogEntry,
21
19
  JobResult,
22
20
  ObjectChange,
23
21
  Role,
24
22
  Status,
25
23
  )
26
- from nautobot.ipam.models import Prefix
27
24
  from nautobot.users.models import ObjectPermission
28
25
 
29
26
 
@@ -221,76 +218,6 @@ class ImportObjectsTestCase(TransactionTestCase):
221
218
  )
222
219
  self.assertEqual(4, Status.objects.filter(name__startswith="test_status").count())
223
220
 
224
- def test_csv_import_with_utf_8_with_bom_encoding(self):
225
- """
226
- A superuser running the job with a .csv file with utf_8 with bom encoding should successfully create all specified objects.
227
- Test for bug fix https://github.com/nautobot/nautobot/issues/5812 and https://github.com/nautobot/nautobot/issues/5985
228
- """
229
-
230
- status = Status.objects.get(name="Active").pk
231
- content = f"prefix,status\n192.168.1.1/32,{status}"
232
- content = content.encode("utf-8-sig")
233
- filename = "test.csv"
234
- csv_file = FileProxy.objects.create(name=filename, file=ContentFile(content, name=filename))
235
- job_result = create_job_result_and_run_job(
236
- "nautobot.core.jobs",
237
- "ImportObjects",
238
- content_type=ContentType.objects.get_for_model(Prefix).pk,
239
- csv_file=csv_file.id,
240
- )
241
- self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
242
- self.assertFalse(
243
- JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_WARNING).exists()
244
- )
245
- self.assertFalse(
246
- JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_ERROR).exists()
247
- )
248
- self.assertEqual(
249
- 1, Prefix.objects.filter(status=Status.objects.get(name="Active"), prefix="192.168.1.1/32").count()
250
- )
251
- mfr = Manufacturer.objects.create(name="Test Cisco Manufacturer")
252
- device_type = DeviceType.objects.create(
253
- manufacturer=mfr,
254
- model="Cisco CSR1000v",
255
- u_height=0,
256
- )
257
- location_type = LocationType.objects.create(name="Test Location Type")
258
- location_type.content_types.set([ContentType.objects.get_for_model(Device)])
259
- location = Location.objects.create(
260
- name="Device Location",
261
- location_type=location_type,
262
- status=Status.objects.get_for_model(Location).first(),
263
- )
264
- role = Role.objects.create(name="Device Status")
265
- role.content_types.set([ContentType.objects.get_for_model(Device)])
266
- content = "\n".join(
267
- [
268
- "serial,asset_tag,device_type,location,status,name,role",
269
- f"1021C4,CA211,{device_type.pk},{location.pk},{status},Test-AC-01,{role}",
270
- f"1021C5,CA212,{device_type.pk},{location.pk},{status},Test-AC-02,{role}",
271
- ]
272
- )
273
- content = content.encode("utf-8-sig")
274
- filename = "test.csv"
275
- csv_file = FileProxy.objects.create(name=filename, file=ContentFile(content, name=filename))
276
- job_result = create_job_result_and_run_job(
277
- "nautobot.core.jobs",
278
- "ImportObjects",
279
- content_type=ContentType.objects.get_for_model(Device).pk,
280
- csv_file=csv_file.id,
281
- )
282
- self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
283
- self.assertFalse(
284
- JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_WARNING).exists()
285
- )
286
- self.assertFalse(
287
- JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_ERROR).exists()
288
- )
289
- device_1 = Device.objects.get(name="Test-AC-01")
290
- device_2 = Device.objects.get(name="Test-AC-02")
291
- self.assertEqual(device_1.serial, "1021C4")
292
- self.assertEqual(device_2.serial, "1021C5")
293
-
294
221
  def test_csv_import_bad_row(self):
295
222
  """A row of incorrect data should fail validation for that object but import all others successfully if `roll_back_if_error` is False."""
296
223
  csv_data = self.csv_data.split("\n")