nautobot 2.3.15b1__py3-none-any.whl → 2.3.16__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 (393) hide show
  1. nautobot/circuits/views.py +3 -3
  2. nautobot/cloud/models.py +1 -1
  3. nautobot/core/api/fields.py +5 -5
  4. nautobot/core/api/serializers.py +9 -9
  5. nautobot/core/api/views.py +3 -2
  6. nautobot/core/apps/__init__.py +5 -2
  7. nautobot/core/celery/schedulers.py +1 -1
  8. nautobot/core/filters.py +19 -16
  9. nautobot/core/forms/fields.py +5 -5
  10. nautobot/core/graphql/types.py +1 -1
  11. nautobot/core/jobs/__init__.py +4 -4
  12. nautobot/core/jobs/cleanup.py +1 -1
  13. nautobot/core/jobs/groups.py +1 -1
  14. nautobot/core/management/commands/validate_models.py +1 -1
  15. nautobot/core/models/__init__.py +1 -1
  16. nautobot/core/models/query_functions.py +2 -2
  17. nautobot/core/models/tree_queries.py +2 -2
  18. nautobot/core/settings.py +3 -0
  19. nautobot/core/settings.yaml +8 -0
  20. nautobot/core/tables.py +5 -5
  21. nautobot/core/templates/inc/media.html +3 -0
  22. nautobot/core/templates/nautobot_config.py.j2 +3 -0
  23. nautobot/core/testing/filters.py +7 -3
  24. nautobot/core/testing/views.py +5 -0
  25. nautobot/core/tests/integration/test_app_home.py +0 -1
  26. nautobot/core/tests/integration/test_app_navbar.py +0 -1
  27. nautobot/core/tests/integration/test_filters.py +0 -2
  28. nautobot/core/tests/integration/test_home.py +0 -1
  29. nautobot/core/tests/integration/test_navbar.py +0 -1
  30. nautobot/core/tests/integration/test_view_authentication.py +1 -0
  31. nautobot/core/tests/runner.py +1 -1
  32. nautobot/core/tests/test_views.py +29 -0
  33. nautobot/core/urls.py +9 -0
  34. nautobot/core/views/generic.py +51 -43
  35. nautobot/core/views/mixins.py +21 -11
  36. nautobot/dcim/api/serializers.py +48 -48
  37. nautobot/dcim/forms.py +2 -0
  38. nautobot/dcim/graphql/types.py +2 -2
  39. nautobot/dcim/models/device_component_templates.py +2 -2
  40. nautobot/dcim/models/device_components.py +22 -20
  41. nautobot/dcim/models/devices.py +1 -1
  42. nautobot/dcim/models/locations.py +3 -3
  43. nautobot/dcim/models/power.py +6 -5
  44. nautobot/dcim/models/racks.py +4 -4
  45. nautobot/dcim/tables/__init__.py +3 -3
  46. nautobot/dcim/tables/devicetypes.py +2 -2
  47. nautobot/dcim/tests/test_filters.py +1 -0
  48. nautobot/dcim/tests/test_graphql.py +52 -0
  49. nautobot/dcim/tests/test_models.py +4 -1
  50. nautobot/dcim/views.py +1 -1
  51. nautobot/extras/api/customfields.py +2 -2
  52. nautobot/extras/api/serializers.py +72 -69
  53. nautobot/extras/api/views.py +4 -4
  54. nautobot/extras/forms/mixins.py +1 -1
  55. nautobot/extras/health_checks.py +1 -2
  56. nautobot/extras/jobs.py +5 -5
  57. nautobot/extras/managers.py +3 -1
  58. nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
  59. nautobot/extras/models/customfields.py +12 -11
  60. nautobot/extras/models/groups.py +13 -9
  61. nautobot/extras/models/jobs.py +4 -4
  62. nautobot/extras/models/models.py +2 -2
  63. nautobot/extras/plugins/views.py +1 -1
  64. nautobot/extras/tables.py +5 -5
  65. nautobot/extras/test_jobs/api_test_job.py +1 -1
  66. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  67. nautobot/extras/test_jobs/dry_run.py +1 -1
  68. nautobot/extras/test_jobs/fail.py +5 -5
  69. nautobot/extras/test_jobs/file_output.py +1 -1
  70. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  71. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  72. nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
  73. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  74. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  75. nautobot/extras/test_jobs/log_redaction.py +1 -1
  76. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  77. nautobot/extras/test_jobs/modify_db.py +1 -1
  78. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  79. nautobot/extras/test_jobs/object_var_required.py +1 -1
  80. nautobot/extras/test_jobs/object_vars.py +1 -1
  81. nautobot/extras/test_jobs/pass.py +3 -3
  82. nautobot/extras/test_jobs/profiling.py +1 -1
  83. nautobot/extras/test_jobs/relative_import.py +3 -3
  84. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  85. nautobot/extras/test_jobs/task_queues.py +1 -1
  86. nautobot/extras/tests/integration/test_plugin_banner.py +0 -2
  87. nautobot/extras/tests/test_api.py +13 -13
  88. nautobot/extras/tests/test_customfields.py +1 -1
  89. nautobot/extras/tests/test_datasources.py +2 -1
  90. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  91. nautobot/extras/tests/test_filters.py +6 -6
  92. nautobot/extras/tests/test_forms.py +20 -1
  93. nautobot/extras/tests/test_jobs.py +11 -11
  94. nautobot/extras/tests/test_models.py +10 -10
  95. nautobot/extras/tests/test_relationships.py +1 -1
  96. nautobot/extras/tests/test_views.py +16 -16
  97. nautobot/extras/views.py +20 -16
  98. nautobot/ipam/api/fields.py +3 -3
  99. nautobot/ipam/api/serializers.py +33 -33
  100. nautobot/ipam/api/views.py +37 -61
  101. nautobot/ipam/querysets.py +2 -2
  102. nautobot/ipam/tests/test_api.py +12 -1
  103. nautobot/ipam/tests/test_forms.py +51 -47
  104. nautobot/ipam/tests/test_migrations.py +30 -30
  105. nautobot/ipam/tests/test_querysets.py +14 -0
  106. nautobot/project-static/docs/404.html +2 -2
  107. nautobot/project-static/docs/apps/index.html +2 -2
  108. nautobot/project-static/docs/apps/nautobot-apps.html +2 -2
  109. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.88dd0f4e.min.js} +2 -2
  110. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.88dd0f4e.min.js.map} +2 -2
  111. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +2 -2
  112. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +2 -2
  113. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +2 -2
  114. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +2 -2
  115. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +2 -2
  116. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +2 -2
  117. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +2 -2
  118. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +2 -2
  119. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +2 -2
  120. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +2 -2
  121. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +2 -2
  122. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +3 -3
  123. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +2 -2
  124. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2 -2
  125. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2 -2
  126. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +2 -2
  127. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +2 -2
  128. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +2 -2
  129. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3 -3
  130. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2 -2
  131. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +2 -2
  132. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2 -2
  133. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +4 -4
  134. nautobot/project-static/docs/development/apps/api/configuration-view.html +2 -2
  135. nautobot/project-static/docs/development/apps/api/database-backend-config.html +2 -2
  136. nautobot/project-static/docs/development/apps/api/models/django-admin.html +2 -2
  137. nautobot/project-static/docs/development/apps/api/models/global-search.html +2 -2
  138. nautobot/project-static/docs/development/apps/api/models/graphql.html +2 -2
  139. nautobot/project-static/docs/development/apps/api/models/index.html +2 -2
  140. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +2 -2
  141. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +2 -2
  142. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +2 -2
  143. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +2 -2
  144. nautobot/project-static/docs/development/apps/api/platform-features/index.html +2 -2
  145. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +2 -2
  146. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +2 -2
  147. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +2 -2
  148. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +2 -2
  149. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +2 -2
  150. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +2 -2
  151. nautobot/project-static/docs/development/apps/api/prometheus.html +2 -2
  152. nautobot/project-static/docs/development/apps/api/setup.html +2 -2
  153. nautobot/project-static/docs/development/apps/api/testing.html +2 -2
  154. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +2 -2
  155. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +2 -2
  156. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +2 -2
  157. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +2 -2
  158. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +2 -2
  159. nautobot/project-static/docs/development/apps/api/views/base-template.html +2 -2
  160. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +2 -2
  161. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +2 -2
  162. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +2 -2
  163. nautobot/project-static/docs/development/apps/api/views/index.html +2 -2
  164. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +2 -2
  165. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +2 -2
  166. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +2 -2
  167. nautobot/project-static/docs/development/apps/api/views/notes.html +2 -2
  168. nautobot/project-static/docs/development/apps/api/views/rest-api.html +2 -2
  169. nautobot/project-static/docs/development/apps/api/views/urls.html +2 -2
  170. nautobot/project-static/docs/development/apps/index.html +2 -2
  171. nautobot/project-static/docs/development/apps/migration/code-updates.html +2 -2
  172. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +2 -2
  173. nautobot/project-static/docs/development/apps/migration/from-v1.html +2 -2
  174. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +2 -2
  175. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +2 -2
  176. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +2 -2
  177. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +2 -2
  178. nautobot/project-static/docs/development/apps/porting-from-netbox.html +2 -2
  179. nautobot/project-static/docs/development/core/application-registry.html +2 -2
  180. nautobot/project-static/docs/development/core/best-practices.html +2 -2
  181. nautobot/project-static/docs/development/core/bootstrap-ui.html +2 -2
  182. nautobot/project-static/docs/development/core/caching.html +2 -2
  183. nautobot/project-static/docs/development/core/controllers.html +2 -2
  184. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +27 -70
  185. nautobot/project-static/docs/development/core/generic-views.html +2 -2
  186. nautobot/project-static/docs/development/core/getting-started.html +2 -2
  187. nautobot/project-static/docs/development/core/homepage.html +2 -2
  188. nautobot/project-static/docs/development/core/index.html +2 -2
  189. nautobot/project-static/docs/development/core/model-checklist.html +2 -2
  190. nautobot/project-static/docs/development/core/model-features.html +2 -2
  191. nautobot/project-static/docs/development/core/natural-keys.html +2 -2
  192. nautobot/project-static/docs/development/core/navigation-menu.html +2 -2
  193. nautobot/project-static/docs/development/core/release-checklist.html +2 -2
  194. nautobot/project-static/docs/development/core/role-internals.html +2 -2
  195. nautobot/project-static/docs/development/core/settings.html +2 -2
  196. nautobot/project-static/docs/development/core/style-guide.html +2 -2
  197. nautobot/project-static/docs/development/core/templates.html +2 -2
  198. nautobot/project-static/docs/development/core/testing.html +2 -2
  199. nautobot/project-static/docs/development/core/user-preferences.html +2 -2
  200. nautobot/project-static/docs/development/index.html +2 -2
  201. nautobot/project-static/docs/development/jobs/index.html +2 -2
  202. nautobot/project-static/docs/development/jobs/migration/from-v1.html +2 -2
  203. nautobot/project-static/docs/index.html +2 -2
  204. nautobot/project-static/docs/overview/application_stack.html +2 -2
  205. nautobot/project-static/docs/overview/design_philosophy.html +2 -2
  206. nautobot/project-static/docs/release-notes/index.html +2 -2
  207. nautobot/project-static/docs/release-notes/version-1.0.html +2 -2
  208. nautobot/project-static/docs/release-notes/version-1.1.html +2 -2
  209. nautobot/project-static/docs/release-notes/version-1.2.html +2 -2
  210. nautobot/project-static/docs/release-notes/version-1.3.html +2 -2
  211. nautobot/project-static/docs/release-notes/version-1.4.html +2 -2
  212. nautobot/project-static/docs/release-notes/version-1.5.html +2 -2
  213. nautobot/project-static/docs/release-notes/version-1.6.html +2 -2
  214. nautobot/project-static/docs/release-notes/version-2.0.html +2 -2
  215. nautobot/project-static/docs/release-notes/version-2.1.html +2 -2
  216. nautobot/project-static/docs/release-notes/version-2.2.html +2 -2
  217. nautobot/project-static/docs/release-notes/version-2.3.html +471 -220
  218. nautobot/project-static/docs/requirements.txt +2 -2
  219. nautobot/project-static/docs/search/search_index.json +1 -1
  220. nautobot/project-static/docs/sitemap.xml +270 -270
  221. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  222. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +2 -2
  223. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +2 -2
  224. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +2 -2
  225. nautobot/project-static/docs/user-guide/administration/configuration/index.html +2 -2
  226. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +2 -2
  227. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +29 -2
  228. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +2 -2
  229. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +2 -2
  230. nautobot/project-static/docs/user-guide/administration/guides/docker.html +2 -2
  231. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +2 -2
  232. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +2 -2
  233. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +2 -2
  234. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +2 -2
  235. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +2 -2
  236. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +2 -2
  237. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +2 -2
  238. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +2 -2
  239. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +2 -2
  240. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +2 -2
  241. nautobot/project-static/docs/user-guide/administration/installation/index.html +2 -2
  242. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +2 -2
  243. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +2 -2
  244. nautobot/project-static/docs/user-guide/administration/installation/services.html +2 -2
  245. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +2 -2
  246. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +2 -2
  247. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +2 -2
  248. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +2 -2
  249. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +2 -2
  250. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +2 -2
  251. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +2 -2
  252. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +2 -2
  253. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +2 -2
  254. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +2 -2
  255. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +2 -2
  256. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +2 -2
  257. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +2 -2
  258. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +2 -2
  259. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +2 -2
  260. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +2 -2
  261. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +2 -2
  262. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +2 -2
  263. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +2 -2
  264. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +2 -2
  265. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +2 -2
  266. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +2 -2
  267. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +2 -2
  268. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +2 -2
  269. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +2 -2
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +2 -2
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +2 -2
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +2 -2
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +2 -2
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +2 -2
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +2 -2
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +2 -2
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +2 -2
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +2 -2
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +2 -2
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +2 -2
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +2 -2
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +2 -2
  283. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +2 -2
  284. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +2 -2
  285. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +2 -2
  286. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +2 -2
  287. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +2 -2
  288. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +2 -2
  289. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +2 -2
  290. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +2 -2
  291. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +2 -2
  292. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +2 -2
  293. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +2 -2
  294. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +2 -2
  295. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +2 -2
  296. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +2 -2
  297. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +2 -2
  298. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +2 -2
  299. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +2 -2
  300. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +2 -2
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +2 -2
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +2 -2
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +2 -2
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +2 -2
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +2 -2
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +2 -2
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +2 -2
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +2 -2
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +2 -2
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +2 -2
  311. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +2 -2
  312. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +2 -2
  313. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +2 -2
  314. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +2 -2
  315. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +2 -2
  316. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +2 -2
  317. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +2 -2
  318. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +2 -2
  319. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +2 -2
  320. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +2 -2
  321. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +2 -2
  322. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +2 -2
  323. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +2 -2
  324. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +2 -2
  325. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +2 -2
  326. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +2 -2
  327. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +2 -2
  328. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +2 -2
  329. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +2 -2
  330. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +2 -2
  331. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +2 -2
  332. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +2 -2
  333. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +2 -2
  334. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +2 -2
  335. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +2 -2
  336. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +2 -2
  337. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +2 -2
  338. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +2 -2
  339. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +2 -2
  340. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +2 -2
  341. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +2 -2
  342. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +2 -2
  343. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +2 -2
  344. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +2 -2
  345. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +2 -2
  346. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +2 -2
  347. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +2 -2
  348. nautobot/project-static/docs/user-guide/index.html +2 -2
  349. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +2 -2
  350. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +2 -2
  351. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +2 -2
  352. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +2 -2
  353. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +2 -2
  354. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +2 -2
  355. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +2 -2
  356. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +2 -2
  357. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +2 -2
  358. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +2 -2
  359. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +2 -2
  360. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +2 -2
  361. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +2 -2
  362. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +2 -2
  363. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +2 -2
  364. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +2 -2
  365. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +2 -2
  366. nautobot/project-static/docs/user-guide/platform-functionality/note.html +2 -2
  367. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +2 -2
  368. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +2 -2
  369. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +2 -2
  370. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +2 -2
  371. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +2 -2
  372. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +2 -2
  373. nautobot/project-static/docs/user-guide/platform-functionality/role.html +2 -2
  374. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +2 -2
  375. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +2 -2
  376. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +2 -2
  377. nautobot/project-static/docs/user-guide/platform-functionality/status.html +2 -2
  378. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +2 -2
  379. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +2 -2
  380. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +2 -2
  381. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +2 -2
  382. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +2 -2
  383. nautobot/users/admin.py +1 -1
  384. nautobot/users/api/serializers.py +4 -4
  385. nautobot/users/api/views.py +1 -1
  386. nautobot/virtualization/api/serializers.py +4 -4
  387. {nautobot-2.3.15b1.dist-info → nautobot-2.3.16.dist-info}/METADATA +5 -4
  388. {nautobot-2.3.15b1.dist-info → nautobot-2.3.16.dist-info}/RECORD +392 -393
  389. {nautobot-2.3.15b1.dist-info → nautobot-2.3.16.dist-info}/WHEEL +1 -1
  390. nautobot/core/fixtures/user-data.json +0 -59
  391. {nautobot-2.3.15b1.dist-info → nautobot-2.3.16.dist-info}/LICENSE.txt +0 -0
  392. {nautobot-2.3.15b1.dist-info → nautobot-2.3.16.dist-info}/NOTICE +0 -0
  393. {nautobot-2.3.15b1.dist-info → nautobot-2.3.16.dist-info}/entry_points.txt +0 -0
@@ -138,7 +138,7 @@ class ModularComponentModel(ComponentModel):
138
138
  @property
139
139
  def parent(self):
140
140
  """Device that this component belongs to, walking up module inheritance if necessary."""
141
- return self.module.device if self.module else self.device
141
+ return self.module.device if self.module else self.device # pylint: disable=no-member
142
142
 
143
143
  def render_name_template(self, save=False):
144
144
  """
@@ -161,9 +161,9 @@ class ModularComponentModel(ComponentModel):
161
161
 
162
162
  The deeply nested interface would be named "A{module.parent}" after calling this method.
163
163
  """
164
- if self.module and self.module.parent_module_bay and "{module" in self.name:
164
+ if self.module and self.module.parent_module_bay and "{module" in self.name: # pylint: disable=no-member
165
165
  name = ""
166
- module_bay = self.module.parent_module_bay
166
+ module_bay = self.module.parent_module_bay # pylint: disable=no-member
167
167
  positions = []
168
168
  while module_bay is not None:
169
169
  position = getattr(module_bay, "position", None)
@@ -291,11 +291,11 @@ class PathEndpoint(models.Model):
291
291
  return []
292
292
 
293
293
  # Construct the complete path
294
- path = [self, *self._path.get_path()]
294
+ path = [self, *self._path.get_path()] # pylint: disable=no-member
295
295
  while (len(path) + 1) % 3:
296
296
  # Pad to ensure we have complete three-tuples (e.g. for paths that end at a RearPort)
297
297
  path.append(None)
298
- path.append(self._path.destination)
298
+ path.append(self._path.destination) # pylint: disable=no-member
299
299
 
300
300
  # Return the path as a list of three-tuples (A termination, cable, B termination)
301
301
  return list(zip(*[iter(path)] * 3))
@@ -555,7 +555,7 @@ class BaseInterface(RelationshipModel):
555
555
 
556
556
  def clean(self):
557
557
  # Remove untagged VLAN assignment for non-802.1Q interfaces
558
- if not self.mode and self.untagged_vlan is not None:
558
+ if not self.mode and self.untagged_vlan is not None: # pylint: disable=no-member # Intf/VMIntf both have untagged_vlan
559
559
  raise ValidationError({"untagged_vlan": "Mode must be set when specifying untagged_vlan"})
560
560
 
561
561
  def save(self, *args, **kwargs):
@@ -569,8 +569,8 @@ class BaseInterface(RelationshipModel):
569
569
  self.status = status
570
570
 
571
571
  # Only "tagged" interfaces may have tagged VLANs assigned. ("tagged all" implies all VLANs are assigned.)
572
- if self.present_in_database and self.mode != InterfaceModeChoices.MODE_TAGGED:
573
- self.tagged_vlans.clear()
572
+ if self.present_in_database and self.mode != InterfaceModeChoices.MODE_TAGGED: # pylint: disable=no-member
573
+ self.tagged_vlans.clear() # pylint: disable=no-member # Intf/VMIntf both have tagged_vlans
574
574
 
575
575
  return super().save(*args, **kwargs)
576
576
 
@@ -710,18 +710,19 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
710
710
  )
711
711
 
712
712
  # An interface's parent must belong to the same device or virtual chassis
713
- if self.parent and self.parent_interface.parent != self.parent:
713
+ if self.parent and self.parent_interface.parent != self.parent: # pylint: disable=no-member
714
714
  if getattr(self.parent, "virtual_chassis", None) is None:
715
715
  raise ValidationError(
716
- {
717
- "parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to a different device "
718
- f"({self.parent_interface.parent})."
716
+ { # pylint: disable=no-member # false positive on parent_interface.parent
717
+ "parent_interface": f"The selected parent interface ({self.parent_interface}) belongs "
718
+ f"to a different device ({self.parent_interface.parent})."
719
719
  }
720
720
  )
721
- elif self.parent_interface.parent.virtual_chassis != self.parent.virtual_chassis:
721
+ elif self.parent_interface.parent.virtual_chassis != self.parent.virtual_chassis: # pylint: disable=no-member
722
722
  raise ValidationError(
723
- {
724
- "parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to {self.parent_interface.parent}, which "
723
+ { # pylint: disable=no-member # false positive on parent_interface.parent
724
+ "parent_interface": f"The selected parent interface ({self.parent_interface}) belongs "
725
+ f"to {self.parent_interface.parent}, which "
725
726
  f"is not part of virtual chassis {self.parent.virtual_chassis}."
726
727
  }
727
728
  )
@@ -754,21 +755,22 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
754
755
  raise ValidationError({"bridge": "An interface cannot be bridged to itself."})
755
756
 
756
757
  # A bridged interface belong to the same device or virtual chassis
757
- if self.parent and self.bridge.parent != self.parent:
758
+ if self.parent and self.bridge.parent != self.parent: # pylint: disable=no-member
758
759
  if getattr(self.parent, "virtual_chassis", None) is None:
759
760
  raise ValidationError(
760
761
  {
761
762
  "bridge": (
763
+ # pylint: disable=no-member # false positive on bridge.parent
762
764
  f"The selected bridge interface ({self.bridge}) belongs to a different device "
763
765
  f"({self.bridge.parent})."
764
766
  )
765
767
  }
766
768
  )
767
- elif self.bridge.parent.virtual_chassis_id != self.parent.virtual_chassis_id:
769
+ elif self.bridge.parent.virtual_chassis_id != self.parent.virtual_chassis_id: # pylint: disable=no-member
768
770
  raise ValidationError(
769
771
  {
770
772
  "bridge": (
771
- f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.parent}, which "
773
+ f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.parent}, which " # pylint: disable=no-member
772
774
  f"is not part of virtual chassis {self.parent.virtual_chassis}."
773
775
  )
774
776
  }
@@ -1084,8 +1086,8 @@ class DeviceBay(ComponentModel):
1084
1086
  super().clean()
1085
1087
 
1086
1088
  # Validate that the parent Device can have DeviceBays
1087
- if not self.device.device_type.is_parent_device:
1088
- raise ValidationError(f"This type of device ({self.device.device_type}) does not support device bays.")
1089
+ if not self.device.device_type.is_parent_device: # pylint: disable=no-member
1090
+ raise ValidationError(f"This type of device ({self.device.device_type}) does not support device bays.") # pylint: disable=no-member
1089
1091
 
1090
1092
  # Cannot install a device into itself, obviously
1091
1093
  if self.device == self.installed_device:
@@ -1466,7 +1466,7 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
1466
1466
  if self.controller == self._original_controller and self.parent == self._original_parent:
1467
1467
  return
1468
1468
 
1469
- if self.parent and self.controller and self.controller != self.parent.controller:
1469
+ if self.parent and self.controller and self.controller != self.parent.controller: # pylint: disable=no-member
1470
1470
  raise ValidationError(
1471
1471
  {"controller": "Controller device group must have the same controller as the parent group."}
1472
1472
  )
@@ -283,7 +283,7 @@ class Location(TreeModel, PrimaryModel):
283
283
  # We shouldn't have a parent, *unless* our own location type is permitted to be nested.
284
284
  if self.parent is not None:
285
285
  if self.location_type.nestable:
286
- if self.parent.location_type != self.location_type:
286
+ if self.parent.location_type != self.location_type: # pylint: disable=no-member
287
287
  raise ValidationError(
288
288
  {
289
289
  "parent": f"A Location of type {self.location_type} may only have "
@@ -304,7 +304,7 @@ class Location(TreeModel, PrimaryModel):
304
304
 
305
305
  # Is the parent location of a correct type?
306
306
  if self.location_type.nestable:
307
- if self.parent.location_type not in (self.location_type, self.location_type.parent):
307
+ if self.parent.location_type not in (self.location_type, self.location_type.parent): # pylint: disable=no-member
308
308
  raise ValidationError(
309
309
  {
310
310
  "parent": f"A Location of type {self.location_type} can only have a Location "
@@ -312,7 +312,7 @@ class Location(TreeModel, PrimaryModel):
312
312
  }
313
313
  )
314
314
  else:
315
- if self.parent.location_type != self.location_type.parent:
315
+ if self.parent.location_type != self.location_type.parent: # pylint: disable=no-member
316
316
  raise ValidationError(
317
317
  {
318
318
  "parent": f"A Location of type {self.location_type} can only have a Location "
@@ -73,11 +73,11 @@ class PowerPanel(PrimaryModel):
73
73
  if self.rack_group:
74
74
  if (
75
75
  self.location is not None
76
- and self.rack_group.location is not None
77
- and self.rack_group.location not in self.location.ancestors(include_self=True)
76
+ and self.rack_group.location is not None # pylint: disable=no-member
77
+ and self.rack_group.location not in self.location.ancestors(include_self=True) # pylint: disable=no-member
78
78
  ):
79
79
  raise ValidationError(
80
- {
80
+ { # pylint: disable=no-member # false positive on rack_group.location
81
81
  "rack_group": f'Rack group "{self.rack_group}" belongs to a location '
82
82
  f'("{self.rack_group.location}") that does not contain "{self.location}".'
83
83
  }
@@ -151,9 +151,10 @@ class PowerFeed(PrimaryModel, PathEndpoint, CableTermination):
151
151
  super().clean()
152
152
 
153
153
  # Rack must belong to same Location as PowerPanel
154
- if self.rack and self.rack.location != self.power_panel.location:
154
+ if self.rack and self.rack.location != self.power_panel.location: # pylint: disable=no-member
155
155
  raise ValidationError(
156
- f"Rack {self.rack} ({self.rack.location}) and power panel {self.power_panel} ({self.power_panel.location}) are in different locations"
156
+ f"Rack {self.rack} ({self.rack.location}) and " # pylint: disable=no-member
157
+ f"power panel {self.power_panel} ({self.power_panel.location}) are in different locations"
157
158
  )
158
159
 
159
160
  # AC voltage cannot be negative
@@ -77,11 +77,11 @@ class RackGroup(TreeModel, OrganizationalModel):
77
77
  # Parent RackGroup (if any) must belong to the same or ancestor Location
78
78
  if (
79
79
  self.parent is not None
80
- and self.parent.location is not None
81
- and self.parent.location not in self.location.ancestors(include_self=True)
80
+ and self.parent.location is not None # pylint: disable=no-member
81
+ and self.parent.location not in self.location.ancestors(include_self=True) # pylint: disable=no-member
82
82
  ):
83
83
  raise ValidationError(
84
- {
84
+ { # pylint: disable=no-member # false positive on parent.location
85
85
  "location": f'Location "{self.location}" is not descended from '
86
86
  f'parent rack group "{self.parent}" location "{self.parent.location}".'
87
87
  }
@@ -296,7 +296,7 @@ class Rack(PrimaryModel):
296
296
  # Determine which devices the user has permission to view
297
297
  permitted_device_ids = []
298
298
  if user is not None:
299
- permitted_device_ids = self.devices.restrict(user, "view").values_list("pk", flat=True)
299
+ permitted_device_ids = self.devices.restrict(user, "view").values_list("pk", flat=True) # pylint: disable=no-member
300
300
 
301
301
  for device in queryset:
302
302
  if expand_devices:
@@ -143,7 +143,7 @@ class ConsoleConnectionTable(BaseTable):
143
143
  linkify=True,
144
144
  verbose_name="Port",
145
145
  )
146
- device = tables.Column(linkify=True, accessor="parent")
146
+ device = tables.Column(linkify=True, accessor="parent", orderable=False)
147
147
  name = tables.Column(linkify=True, verbose_name="Console Port")
148
148
  reachable = BooleanColumn(accessor=Accessor("_path__is_active"), verbose_name="Reachable")
149
149
 
@@ -171,7 +171,7 @@ class PowerConnectionTable(BaseTable):
171
171
  linkify=True,
172
172
  verbose_name="Outlet",
173
173
  )
174
- device = tables.Column(linkify=True, accessor="parent")
174
+ device = tables.Column(linkify=True, accessor="parent", orderable=False)
175
175
  name = tables.Column(linkify=True, verbose_name="Power Port")
176
176
  reachable = BooleanColumn(accessor=Accessor("_path__is_active"), verbose_name="Reachable")
177
177
 
@@ -181,7 +181,7 @@ class PowerConnectionTable(BaseTable):
181
181
 
182
182
 
183
183
  class InterfaceConnectionTable(BaseTable):
184
- device_a = tables.Column(accessor=Accessor("parent"), linkify=True, verbose_name="Device A")
184
+ device_a = tables.Column(accessor=Accessor("parent"), linkify=True, verbose_name="Device A", orderable=False)
185
185
  interface_a = tables.Column(accessor=Accessor("name"), linkify=True, verbose_name="Interface A")
186
186
  device_b = tables.Column(
187
187
  accessor=Accessor("_path__destination__parent"),
@@ -253,7 +253,7 @@ class PowerOutletTemplateTable(ComponentTemplateTable):
253
253
  "name",
254
254
  "label",
255
255
  "type",
256
- "power_port",
256
+ "power_port_template",
257
257
  "feed_leg",
258
258
  "description",
259
259
  "actions",
@@ -290,7 +290,7 @@ class FrontPortTemplateTable(ComponentTemplateTable):
290
290
  "name",
291
291
  "label",
292
292
  "type",
293
- "rear_port",
293
+ "rear_port_template",
294
294
  "rear_port_position",
295
295
  "description",
296
296
  "actions",
@@ -1,3 +1,4 @@
1
+ # pylint: disable=no-member # it doesn't recognize the class attributes assigned in common_test_data()
1
2
  import uuid
2
3
 
3
4
  from django.contrib.auth import get_user_model
@@ -83,3 +83,55 @@ class GraphQLTestCase(TestCase):
83
83
  self.assertEqual(
84
84
  resp["data"]["devices"][0]["platform"]["network_driver_mappings"]["scrapli"], "cisco_iosxe"
85
85
  )
86
+
87
+ with self.subTest("device serial number query"):
88
+ non_empty_serial_device = Device.objects.first()
89
+ non_empty_serial_device.serial = "1234567890abceFGHIJKL"
90
+ non_empty_serial_device.save()
91
+
92
+ # Test device serial query default behavior: serial__ie
93
+ query = 'query { devices (serial: " ") { name serial } }'
94
+ resp = execute_query(query, user=self.user).to_dict()
95
+ self.assertFalse(resp["data"].get("error"))
96
+ for device in resp["data"]["devices"]:
97
+ self.assertEqual(device["serial"], "")
98
+
99
+ # Test device serial default filter with non-empty serial number
100
+ query = 'query { devices (serial:"' + non_empty_serial_device.serial.lower() + '") { name serial } }'
101
+ resp = execute_query(query, user=self.user).to_dict()
102
+ self.assertFalse(resp["data"].get("error"))
103
+ self.assertEqual(resp["data"]["devices"][0]["serial"], non_empty_serial_device.serial)
104
+
105
+ # Test device serial iexact filter with non-empty serial number
106
+ query = 'query { devices (serial__ie:"' + non_empty_serial_device.serial.upper() + '") { name serial } }'
107
+ resp = execute_query(query, user=self.user).to_dict()
108
+ self.assertFalse(resp["data"].get("error"))
109
+ self.assertEqual(resp["data"]["devices"][0]["serial"], non_empty_serial_device.serial)
110
+
111
+ # Test device serial__nie filter with non-empty serial number
112
+ query = 'query { devices (serial__nie:"' + non_empty_serial_device.serial.lower() + '") { name serial } }'
113
+ resp = execute_query(query, user=self.user).to_dict()
114
+ self.assertFalse(resp["data"].get("error"))
115
+ for device in resp["data"]["devices"]:
116
+ self.assertNotEqual(device["serial"], non_empty_serial_device.serial)
117
+
118
+ # Test device serial__ie filter with empty serial number
119
+ query = 'query { devices (serial__ie:" ") { name serial } }'
120
+ resp = execute_query(query, user=self.user).to_dict()
121
+ self.assertFalse(resp["data"].get("error"))
122
+ for device in resp["data"]["devices"]:
123
+ self.assertEqual(device["serial"], "")
124
+
125
+ # Test device serial__nie filter with empty serial number
126
+ query = 'query { devices (serial__nie:" ") { name serial } }'
127
+ resp = execute_query(query, user=self.user).to_dict()
128
+ self.assertFalse(resp["data"].get("error"))
129
+ for device in resp["data"]["devices"]:
130
+ self.assertNotEqual(device["serial"], "")
131
+
132
+ # Test device serial__n filter with empty serial number
133
+ query = 'query { devices (serial__n:" ") { name serial } }'
134
+ resp = execute_query(query, user=self.user).to_dict()
135
+ self.assertFalse(resp["data"].get("error"))
136
+ for device in resp["data"]["devices"]:
137
+ self.assertNotEqual(device["serial"], "")
@@ -1,9 +1,12 @@
1
+ from __future__ import annotations # python 3.8
2
+
1
3
  from decimal import Decimal
2
4
 
3
5
  from constance.test import override_config
4
6
  from django.contrib.contenttypes.models import ContentType
5
7
  from django.core.exceptions import ValidationError
6
8
  from django.db import IntegrityError
9
+ from django.db.models import Model
7
10
  from django.test import TestCase
8
11
  from django.test.utils import override_settings
9
12
 
@@ -76,7 +79,7 @@ class ModularDeviceComponentTestCaseMixin:
76
79
 
77
80
  # fields required to create instances of the model, with the exception of name, device_field and module_field
78
81
  modular_component_create_data = {}
79
- model = None
82
+ model: type[Model]
80
83
  device_field = "device" # field name for the parent device
81
84
  module_field = "module" # field name for the parent module
82
85
 
nautobot/dcim/views.py CHANGED
@@ -699,7 +699,7 @@ class RackReservationEditView(generic.ObjectEditView):
699
699
  model_form = forms.RackReservationForm
700
700
  template_name = "dcim/rackreservation_edit.html"
701
701
 
702
- def alter_obj(self, obj, request, args, kwargs):
702
+ def alter_obj(self, obj, request, url_args, url_kwargs):
703
703
  if not obj.present_in_database:
704
704
  if "rack" in request.GET:
705
705
  obj.rack = get_object_or_404(Rack, pk=request.GET.get("rack"))
@@ -42,8 +42,8 @@ class CustomFieldsDataField(Field):
42
42
  def custom_field_keys(self):
43
43
  return CustomField.objects.keys_for_model(self.parent.Meta.model)
44
44
 
45
- def to_representation(self, obj):
46
- return {key: obj.get(key) for key in self.custom_field_keys}
45
+ def to_representation(self, value):
46
+ return {key: value.get(key) for key in self.custom_field_keys}
47
47
 
48
48
  def to_internal_value(self, data):
49
49
  """Support updates to individual fields on an existing instance without needing to provide the entire dict."""