nautobot 2.3.11__py3-none-any.whl → 2.3.13__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 (516) hide show
  1. nautobot/core/api/serializers.py +1 -0
  2. nautobot/core/celery/log.py +4 -4
  3. nautobot/core/models/tree_queries.py +5 -2
  4. nautobot/core/settings.py +26 -0
  5. nautobot/core/settings.yaml +31 -0
  6. nautobot/core/tables.py +60 -10
  7. nautobot/core/templates/generic/object_notes.html +1 -1
  8. nautobot/core/templates/generic/object_retrieve.html +1 -1
  9. nautobot/core/templatetags/helpers.py +7 -1
  10. nautobot/core/testing/api.py +5 -1
  11. nautobot/core/testing/views.py +15 -4
  12. nautobot/core/tests/test_api.py +20 -0
  13. nautobot/core/tests/test_csv.py +25 -3
  14. nautobot/core/tests/test_utils.py +8 -0
  15. nautobot/core/utils/lookup.py +11 -8
  16. nautobot/dcim/api/views.py +3 -0
  17. nautobot/dcim/choices.py +6 -0
  18. nautobot/dcim/filters/__init__.py +26 -1
  19. nautobot/dcim/forms.py +4 -0
  20. nautobot/dcim/tables/devices.py +2 -6
  21. nautobot/dcim/templates/dcim/controller_retrieve.html +1 -1
  22. nautobot/dcim/templates/dcim/device/base.html +1 -1
  23. nautobot/dcim/tests/test_filters.py +33 -0
  24. nautobot/dcim/tests/test_views.py +6 -0
  25. nautobot/extras/api/serializers.py +1 -0
  26. nautobot/extras/api/views.py +2 -0
  27. nautobot/extras/forms/forms.py +2 -0
  28. nautobot/extras/group_sync.py +42 -0
  29. nautobot/extras/models/metadata.py +1 -0
  30. nautobot/extras/models/models.py +1 -1
  31. nautobot/extras/plugins/__init__.py +15 -3
  32. nautobot/extras/tables.py +1 -0
  33. nautobot/extras/templates/extras/inc/job_table.html +1 -1
  34. nautobot/extras/tests/test_views.py +2 -2
  35. nautobot/extras/views.py +0 -2
  36. nautobot/ipam/lookups.py +101 -62
  37. nautobot/ipam/tables.py +22 -15
  38. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -1
  39. nautobot/ipam/tests/test_querysets.py +49 -1
  40. nautobot/ipam/utils/__init__.py +24 -0
  41. nautobot/ipam/views.py +61 -68
  42. nautobot/project-static/docs/404.html +10 -10
  43. nautobot/project-static/docs/additional-features/caching.html +1 -2
  44. nautobot/project-static/docs/additional-features/change-logging.html +1 -2
  45. nautobot/project-static/docs/additional-features/config-contexts.html +1 -2
  46. nautobot/project-static/docs/additional-features/healthcheck.html +1 -2
  47. nautobot/project-static/docs/additional-features/jobs.html +1 -2
  48. nautobot/project-static/docs/additional-features/prometheus-metrics.html +1 -2
  49. nautobot/project-static/docs/administration/celery-queues.html +1 -2
  50. nautobot/project-static/docs/administration/nautobot-server.html +1 -2
  51. nautobot/project-static/docs/administration/nautobot-shell.html +1 -2
  52. nautobot/project-static/docs/administration/permissions.html +1 -2
  53. nautobot/project-static/docs/administration/replicating-nautobot.html +1 -2
  54. nautobot/project-static/docs/apps/index.html +10 -10
  55. nautobot/project-static/docs/apps/migrating-jobs-from-nautobot-v1.html +1 -2
  56. nautobot/project-static/docs/apps/nautobot-apps.html +10 -10
  57. nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css +1 -0
  58. nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css.map +1 -0
  59. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +10 -10
  60. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +10 -10
  61. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +10 -10
  62. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +10 -10
  63. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +10 -10
  64. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +10 -10
  65. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +10 -10
  66. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +10 -10
  67. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +10 -10
  68. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +10 -10
  69. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +10 -10
  70. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +10 -10
  71. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +10 -10
  72. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +10 -10
  73. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +10 -10
  74. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +10 -10
  75. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +10 -10
  76. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +206 -14
  77. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +10 -10
  78. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +10 -10
  79. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +10 -10
  80. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +25 -11
  81. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +10 -10
  82. nautobot/project-static/docs/configuration/authentication/ldap.html +1 -2
  83. nautobot/project-static/docs/configuration/authentication/remote.html +1 -2
  84. nautobot/project-static/docs/configuration/authentication/sso.html +1 -2
  85. nautobot/project-static/docs/configuration/index.html +1 -2
  86. nautobot/project-static/docs/configuration/optional-settings.html +1 -2
  87. nautobot/project-static/docs/configuration/required-settings.html +1 -2
  88. nautobot/project-static/docs/core-functionality/circuits.html +1 -2
  89. nautobot/project-static/docs/core-functionality/device-types.html +1 -2
  90. nautobot/project-static/docs/core-functionality/devices.html +1 -2
  91. nautobot/project-static/docs/core-functionality/ipam.html +1 -2
  92. nautobot/project-static/docs/core-functionality/power.html +1 -2
  93. nautobot/project-static/docs/core-functionality/secrets.html +1 -2
  94. nautobot/project-static/docs/core-functionality/services.html +1 -2
  95. nautobot/project-static/docs/core-functionality/sites-and-racks.html +1 -2
  96. nautobot/project-static/docs/core-functionality/tenancy.html +1 -2
  97. nautobot/project-static/docs/core-functionality/virtualization.html +1 -2
  98. nautobot/project-static/docs/core-functionality/vlans.html +1 -2
  99. nautobot/project-static/docs/development/application-registry.html +1 -2
  100. nautobot/project-static/docs/development/apps/api/configuration-view.html +10 -10
  101. nautobot/project-static/docs/development/apps/api/database-backend-config.html +10 -10
  102. nautobot/project-static/docs/development/apps/api/models/django-admin.html +10 -10
  103. nautobot/project-static/docs/development/apps/api/models/global-search.html +10 -10
  104. nautobot/project-static/docs/development/apps/api/models/graphql.html +10 -10
  105. nautobot/project-static/docs/development/apps/api/models/index.html +10 -10
  106. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +10 -10
  107. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +10 -10
  108. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +10 -10
  109. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +10 -10
  110. nautobot/project-static/docs/development/apps/api/platform-features/index.html +10 -10
  111. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +10 -10
  112. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +10 -10
  113. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +10 -10
  114. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +10 -10
  115. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +32 -13
  116. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +10 -10
  117. nautobot/project-static/docs/development/apps/api/prometheus.html +10 -10
  118. nautobot/project-static/docs/development/apps/api/setup.html +10 -10
  119. nautobot/project-static/docs/development/apps/api/testing.html +10 -10
  120. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +10 -10
  121. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +10 -10
  122. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +10 -10
  123. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +10 -10
  124. nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +1 -2
  125. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +10 -10
  126. nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +1 -2
  127. nautobot/project-static/docs/development/apps/api/views/base-template.html +10 -10
  128. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +10 -10
  129. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +10 -10
  130. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +10 -10
  131. nautobot/project-static/docs/development/apps/api/views/index.html +10 -10
  132. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +10 -10
  133. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +10 -10
  134. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +10 -10
  135. nautobot/project-static/docs/development/apps/api/views/notes.html +10 -10
  136. nautobot/project-static/docs/development/apps/api/views/rest-api.html +10 -10
  137. nautobot/project-static/docs/development/apps/api/views/urls.html +10 -10
  138. nautobot/project-static/docs/development/apps/api/views/view-overrides.html +1 -2
  139. nautobot/project-static/docs/development/apps/index.html +10 -10
  140. nautobot/project-static/docs/development/apps/migration/code-updates.html +10 -10
  141. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +10 -10
  142. nautobot/project-static/docs/development/apps/migration/from-v1.html +10 -10
  143. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +10 -10
  144. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +10 -10
  145. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +10 -10
  146. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +10 -10
  147. nautobot/project-static/docs/development/apps/porting-from-netbox.html +10 -10
  148. nautobot/project-static/docs/development/best-practices.html +1 -2
  149. nautobot/project-static/docs/development/core/application-registry.html +10 -10
  150. nautobot/project-static/docs/development/core/best-practices.html +10 -10
  151. nautobot/project-static/docs/development/core/bootstrap-ui.html +10 -10
  152. nautobot/project-static/docs/development/core/caching.html +10 -10
  153. nautobot/project-static/docs/development/core/controllers.html +10 -10
  154. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +10 -10
  155. nautobot/project-static/docs/development/core/extending-models.html +1 -2
  156. nautobot/project-static/docs/development/core/generic-views.html +10 -10
  157. nautobot/project-static/docs/development/core/getting-started.html +10 -10
  158. nautobot/project-static/docs/development/core/homepage.html +10 -10
  159. nautobot/project-static/docs/development/core/index.html +10 -10
  160. nautobot/project-static/docs/development/core/model-checklist.html +10 -10
  161. nautobot/project-static/docs/development/core/model-features.html +10 -10
  162. nautobot/project-static/docs/development/core/natural-keys.html +10 -10
  163. nautobot/project-static/docs/development/core/navigation-menu.html +10 -10
  164. nautobot/project-static/docs/development/core/react-ui.html +1 -2
  165. nautobot/project-static/docs/development/core/release-checklist.html +10 -10
  166. nautobot/project-static/docs/development/core/role-internals.html +10 -10
  167. nautobot/project-static/docs/development/core/settings.html +10 -10
  168. nautobot/project-static/docs/development/core/style-guide.html +10 -10
  169. nautobot/project-static/docs/development/core/templates.html +10 -10
  170. nautobot/project-static/docs/development/core/testing.html +12 -12
  171. nautobot/project-static/docs/development/core/user-preferences.html +10 -10
  172. nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1 -2
  173. nautobot/project-static/docs/development/extending-models.html +1 -2
  174. nautobot/project-static/docs/development/generic-views.html +1 -2
  175. nautobot/project-static/docs/development/getting-started.html +1 -2
  176. nautobot/project-static/docs/development/homepage.html +1 -2
  177. nautobot/project-static/docs/development/index.html +10 -10
  178. nautobot/project-static/docs/development/jobs/index.html +10 -10
  179. nautobot/project-static/docs/development/jobs/migration/from-v1.html +10 -10
  180. nautobot/project-static/docs/development/model-features.html +1 -2
  181. nautobot/project-static/docs/development/natural-keys.html +1 -2
  182. nautobot/project-static/docs/development/navigation-menu.html +1 -2
  183. nautobot/project-static/docs/development/react-ui.html +1 -2
  184. nautobot/project-static/docs/development/release-checklist.html +1 -2
  185. nautobot/project-static/docs/development/role-internals.html +1 -2
  186. nautobot/project-static/docs/development/style-guide.html +1 -2
  187. nautobot/project-static/docs/development/templates.html +1 -2
  188. nautobot/project-static/docs/development/testing.html +1 -2
  189. nautobot/project-static/docs/development/user-preferences.html +1 -2
  190. nautobot/project-static/docs/docker/index.html +1 -2
  191. nautobot/project-static/docs/index.html +10 -10
  192. nautobot/project-static/docs/installation/centos.html +1 -2
  193. nautobot/project-static/docs/installation/external-authentication.html +1 -2
  194. nautobot/project-static/docs/installation/http-server.html +1 -2
  195. nautobot/project-static/docs/installation/index.html +1 -2
  196. nautobot/project-static/docs/installation/migrating-from-netbox.html +1 -2
  197. nautobot/project-static/docs/installation/migrating-from-postgresql.html +1 -2
  198. nautobot/project-static/docs/installation/nautobot.html +1 -2
  199. nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1 -2
  200. nautobot/project-static/docs/installation/selinux-troubleshooting.html +1 -2
  201. nautobot/project-static/docs/installation/services.html +1 -2
  202. nautobot/project-static/docs/installation/ubuntu.html +1 -2
  203. nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +1 -2
  204. nautobot/project-static/docs/installation/upgrading.html +1 -2
  205. nautobot/project-static/docs/models/circuits/circuit.html +1 -2
  206. nautobot/project-static/docs/models/circuits/circuittermination.html +1 -2
  207. nautobot/project-static/docs/models/circuits/circuittype.html +1 -2
  208. nautobot/project-static/docs/models/circuits/provider.html +1 -2
  209. nautobot/project-static/docs/models/circuits/providernetwork.html +1 -2
  210. nautobot/project-static/docs/models/cloud/cloudaccount.html +1 -2
  211. nautobot/project-static/docs/models/cloud/cloudnetwork.html +1 -2
  212. nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +1 -2
  213. nautobot/project-static/docs/models/cloud/cloudresourcetype.html +1 -2
  214. nautobot/project-static/docs/models/cloud/cloudservice.html +1 -2
  215. nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +1 -2
  216. nautobot/project-static/docs/models/dcim/cable.html +1 -2
  217. nautobot/project-static/docs/models/dcim/consoleport.html +1 -2
  218. nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1 -2
  219. nautobot/project-static/docs/models/dcim/consoleserverport.html +1 -2
  220. nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1 -2
  221. nautobot/project-static/docs/models/dcim/controller.html +1 -2
  222. nautobot/project-static/docs/models/dcim/controllermanageddevicegroup.html +1 -2
  223. nautobot/project-static/docs/models/dcim/device.html +1 -2
  224. nautobot/project-static/docs/models/dcim/devicebay.html +1 -2
  225. nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1 -2
  226. nautobot/project-static/docs/models/dcim/devicefamily.html +1 -2
  227. nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1 -2
  228. nautobot/project-static/docs/models/dcim/devicetype.html +1 -2
  229. nautobot/project-static/docs/models/dcim/frontport.html +1 -2
  230. nautobot/project-static/docs/models/dcim/frontporttemplate.html +1 -2
  231. nautobot/project-static/docs/models/dcim/interface.html +1 -2
  232. nautobot/project-static/docs/models/dcim/interfacetemplate.html +1 -2
  233. nautobot/project-static/docs/models/dcim/inventoryitem.html +1 -2
  234. nautobot/project-static/docs/models/dcim/location.html +1 -2
  235. nautobot/project-static/docs/models/dcim/locationtype.html +1 -2
  236. nautobot/project-static/docs/models/dcim/manufacturer.html +1 -2
  237. nautobot/project-static/docs/models/dcim/module.html +1 -2
  238. nautobot/project-static/docs/models/dcim/modulebay.html +1 -2
  239. nautobot/project-static/docs/models/dcim/modulebaytemplate.html +1 -2
  240. nautobot/project-static/docs/models/dcim/moduletype.html +1 -2
  241. nautobot/project-static/docs/models/dcim/platform.html +1 -2
  242. nautobot/project-static/docs/models/dcim/powerfeed.html +1 -2
  243. nautobot/project-static/docs/models/dcim/poweroutlet.html +1 -2
  244. nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1 -2
  245. nautobot/project-static/docs/models/dcim/powerpanel.html +1 -2
  246. nautobot/project-static/docs/models/dcim/powerport.html +1 -2
  247. nautobot/project-static/docs/models/dcim/powerporttemplate.html +1 -2
  248. nautobot/project-static/docs/models/dcim/rack.html +1 -2
  249. nautobot/project-static/docs/models/dcim/rackgroup.html +1 -2
  250. nautobot/project-static/docs/models/dcim/rackreservation.html +1 -2
  251. nautobot/project-static/docs/models/dcim/rearport.html +1 -2
  252. nautobot/project-static/docs/models/dcim/rearporttemplate.html +1 -2
  253. nautobot/project-static/docs/models/dcim/softwareimagefile.html +1 -2
  254. nautobot/project-static/docs/models/dcim/softwareversion.html +1 -2
  255. nautobot/project-static/docs/models/dcim/virtualchassis.html +1 -2
  256. nautobot/project-static/docs/models/extras/computedfield.html +1 -2
  257. nautobot/project-static/docs/models/extras/configcontext.html +1 -2
  258. nautobot/project-static/docs/models/extras/configcontextschema.html +1 -2
  259. nautobot/project-static/docs/models/extras/contact.html +1 -2
  260. nautobot/project-static/docs/models/extras/customfield.html +1 -2
  261. nautobot/project-static/docs/models/extras/customlink.html +1 -2
  262. nautobot/project-static/docs/models/extras/dynamicgroup.html +1 -2
  263. nautobot/project-static/docs/models/extras/exporttemplate.html +1 -2
  264. nautobot/project-static/docs/models/extras/gitrepository.html +1 -2
  265. nautobot/project-static/docs/models/extras/jobhook.html +1 -2
  266. nautobot/project-static/docs/models/extras/joblogentry.html +1 -2
  267. nautobot/project-static/docs/models/extras/jobresult.html +1 -2
  268. nautobot/project-static/docs/models/extras/metadatachoice.html +1 -2
  269. nautobot/project-static/docs/models/extras/metadatatype.html +1 -2
  270. nautobot/project-static/docs/models/extras/objectmetadata.html +1 -2
  271. nautobot/project-static/docs/models/extras/role.html +1 -2
  272. nautobot/project-static/docs/models/extras/savedview.html +1 -2
  273. nautobot/project-static/docs/models/extras/secret.html +1 -2
  274. nautobot/project-static/docs/models/extras/secretsgroup.html +1 -2
  275. nautobot/project-static/docs/models/extras/staticgroupassociation.html +1 -2
  276. nautobot/project-static/docs/models/extras/status.html +1 -2
  277. nautobot/project-static/docs/models/extras/team.html +1 -2
  278. nautobot/project-static/docs/models/ipam/ipaddress.html +1 -2
  279. nautobot/project-static/docs/models/ipam/prefix.html +1 -2
  280. nautobot/project-static/docs/models/ipam/rir.html +1 -2
  281. nautobot/project-static/docs/models/ipam/routetarget.html +1 -2
  282. nautobot/project-static/docs/models/ipam/service.html +1 -2
  283. nautobot/project-static/docs/models/ipam/vlan.html +1 -2
  284. nautobot/project-static/docs/models/ipam/vlangroup.html +1 -2
  285. nautobot/project-static/docs/models/ipam/vrf.html +1 -2
  286. nautobot/project-static/docs/models/tenancy/tenant.html +1 -2
  287. nautobot/project-static/docs/models/tenancy/tenantgroup.html +1 -2
  288. nautobot/project-static/docs/models/virtualization/cluster.html +1 -2
  289. nautobot/project-static/docs/models/virtualization/clustergroup.html +1 -2
  290. nautobot/project-static/docs/models/virtualization/clustertype.html +1 -2
  291. nautobot/project-static/docs/models/virtualization/virtualmachine.html +1 -2
  292. nautobot/project-static/docs/models/virtualization/vminterface.html +1 -2
  293. nautobot/project-static/docs/objects.inv +0 -0
  294. nautobot/project-static/docs/overview/application_stack.html +10 -10
  295. nautobot/project-static/docs/overview/design_philosophy.html +10 -10
  296. nautobot/project-static/docs/overview/index.html +1 -2
  297. nautobot/project-static/docs/plugins/development.html +1 -2
  298. nautobot/project-static/docs/plugins/index.html +1 -2
  299. nautobot/project-static/docs/plugins/porting-from-netbox.html +1 -2
  300. nautobot/project-static/docs/release-notes/index.html +15 -15
  301. nautobot/project-static/docs/release-notes/version-1.0.html +10 -10
  302. nautobot/project-static/docs/release-notes/version-1.1.html +10 -10
  303. nautobot/project-static/docs/release-notes/version-1.2.html +10 -10
  304. nautobot/project-static/docs/release-notes/version-1.3.html +10 -10
  305. nautobot/project-static/docs/release-notes/version-1.4.html +10 -10
  306. nautobot/project-static/docs/release-notes/version-1.5.html +10 -10
  307. nautobot/project-static/docs/release-notes/version-1.6.html +623 -188
  308. nautobot/project-static/docs/release-notes/version-2.0.html +10 -10
  309. nautobot/project-static/docs/release-notes/version-2.1.html +10 -10
  310. nautobot/project-static/docs/release-notes/version-2.2.html +10 -10
  311. nautobot/project-static/docs/release-notes/version-2.3.html +548 -192
  312. nautobot/project-static/docs/requirements.txt +2 -2
  313. nautobot/project-static/docs/rest-api/overview.html +1 -2
  314. nautobot/project-static/docs/search/search_index.json +1 -1
  315. nautobot/project-static/docs/sitemap.xml +270 -270
  316. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  317. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +10 -10
  318. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +10 -10
  319. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +65 -12
  320. nautobot/project-static/docs/user-guide/administration/configuration/index.html +10 -10
  321. nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +1 -2
  322. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1 -2
  323. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +10 -10
  324. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +1 -2
  325. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +122 -10
  326. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +10 -10
  327. nautobot/project-static/docs/user-guide/administration/guides/caching.html +1 -2
  328. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +10 -10
  329. nautobot/project-static/docs/user-guide/administration/guides/docker.html +10 -10
  330. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +10 -10
  331. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +1 -2
  332. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +10 -10
  333. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +10 -10
  334. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +10 -10
  335. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +10 -10
  336. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +10 -10
  337. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +10 -10
  338. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +10 -10
  339. nautobot/project-static/docs/user-guide/administration/installation/docker.html +1 -2
  340. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +10 -10
  341. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +1 -2
  342. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +10 -10
  343. nautobot/project-static/docs/user-guide/administration/installation/index.html +10 -10
  344. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +10 -10
  345. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +10 -10
  346. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +1 -2
  347. nautobot/project-static/docs/user-guide/administration/installation/services.html +10 -10
  348. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +1 -2
  349. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +1 -2
  350. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +1 -2
  351. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +10 -10
  352. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +10 -10
  353. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +10 -10
  354. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +10 -10
  355. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +10 -10
  356. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +10 -10
  357. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +10 -10
  358. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +10 -10
  359. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +10 -10
  360. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +10 -10
  361. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +10 -10
  362. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +10 -10
  363. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +10 -10
  364. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +10 -10
  365. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +10 -10
  366. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +10 -10
  367. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +10 -10
  368. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +10 -10
  369. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +10 -10
  370. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +10 -10
  371. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +10 -10
  372. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +10 -10
  373. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +10 -10
  374. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +10 -10
  375. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +10 -10
  376. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +10 -10
  377. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +10 -10
  378. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +10 -10
  379. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +10 -10
  380. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +10 -10
  381. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +10 -10
  382. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +10 -10
  383. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +10 -10
  384. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +10 -10
  385. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +10 -10
  386. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +10 -10
  387. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +10 -10
  388. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +10 -10
  389. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +10 -10
  390. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +10 -10
  391. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +10 -10
  392. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +10 -10
  393. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +10 -10
  394. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +10 -10
  395. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +10 -10
  396. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +10 -10
  397. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +10 -10
  398. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +10 -10
  399. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +10 -10
  400. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +10 -10
  401. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +10 -10
  402. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +10 -10
  403. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +10 -10
  404. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +10 -10
  405. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +10 -10
  406. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +10 -10
  407. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +10 -10
  408. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +10 -10
  409. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +10 -10
  410. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +10 -10
  411. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +10 -10
  412. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +10 -10
  413. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +10 -10
  414. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +10 -10
  415. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +10 -10
  416. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +10 -10
  417. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +10 -10
  418. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +10 -10
  419. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +10 -10
  420. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +10 -10
  421. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +10 -10
  422. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +10 -10
  423. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +10 -10
  424. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +10 -10
  425. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +10 -10
  426. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +10 -10
  427. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +10 -10
  428. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +10 -10
  429. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +10 -10
  430. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +10 -10
  431. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +10 -10
  432. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +10 -10
  433. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +10 -10
  434. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +10 -10
  435. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +10 -10
  436. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +10 -10
  437. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +10 -10
  438. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +10 -10
  439. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +10 -10
  440. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +10 -10
  441. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +10 -10
  442. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +10 -10
  443. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +10 -10
  444. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +10 -10
  445. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +10 -10
  446. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +10 -10
  447. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +10 -10
  448. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +10 -10
  449. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +10 -10
  450. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +10 -10
  451. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +10 -10
  452. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +10 -10
  453. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +10 -10
  454. nautobot/project-static/docs/user-guide/index.html +10 -10
  455. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +10 -10
  456. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +10 -10
  457. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +10 -10
  458. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +10 -10
  459. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +10 -10
  460. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +10 -10
  461. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +10 -10
  462. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +10 -10
  463. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +10 -10
  464. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +10 -10
  465. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +10 -10
  466. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +10 -10
  467. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +10 -10
  468. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +10 -10
  469. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +10 -10
  470. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +10 -10
  471. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +10 -10
  472. nautobot/project-static/docs/user-guide/platform-functionality/note.html +10 -10
  473. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +10 -10
  474. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +10 -10
  475. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +10 -10
  476. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +10 -10
  477. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +10 -10
  478. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +10 -10
  479. nautobot/project-static/docs/user-guide/platform-functionality/role.html +10 -10
  480. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +10 -10
  481. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +10 -10
  482. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +10 -10
  483. nautobot/project-static/docs/user-guide/platform-functionality/status.html +10 -10
  484. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +10 -10
  485. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +10 -10
  486. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +10 -10
  487. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +10 -10
  488. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +10 -10
  489. nautobot/project-static/docs/user-guides/custom-fields.html +1 -2
  490. nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1 -2
  491. nautobot/project-static/docs/user-guides/getting-started/index.html +1 -2
  492. nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1 -2
  493. nautobot/project-static/docs/user-guides/getting-started/ipam.html +1 -2
  494. nautobot/project-static/docs/user-guides/getting-started/platforms.html +1 -2
  495. nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1 -2
  496. nautobot/project-static/docs/user-guides/getting-started/tenants.html +1 -2
  497. nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1 -2
  498. nautobot/project-static/docs/user-guides/git-data-source.html +1 -2
  499. nautobot/project-static/docs/user-guides/graphql.html +1 -2
  500. nautobot/project-static/docs/user-guides/ip-address-merge-tool.html +1 -2
  501. nautobot/project-static/docs/user-guides/relationships.html +1 -2
  502. nautobot/project-static/docs/user-guides/s3-django-storage.html +1 -2
  503. nautobot/project-static/js/forms.js +10 -0
  504. nautobot/users/api/serializers.py +1 -0
  505. nautobot/virtualization/filters.py +19 -2
  506. nautobot/virtualization/forms.py +3 -3
  507. nautobot/virtualization/templates/virtualization/vminterface.html +4 -0
  508. nautobot/virtualization/tests/test_filters.py +9 -0
  509. {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/METADATA +4 -4
  510. {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/RECORD +514 -513
  511. nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css +0 -1
  512. nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css.map +0 -1
  513. {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/LICENSE.txt +0 -0
  514. {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/NOTICE +0 -0
  515. {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/WHEEL +0 -0
  516. {nautobot-2.3.11.dist-info → nautobot-2.3.13.dist-info}/entry_points.txt +0 -0
@@ -220,13 +220,11 @@ class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
220
220
  )
221
221
 
222
222
 
223
- class DeviceImportTable(BaseTable):
223
+ class DeviceImportTable(StatusTableMixin, RoleTableMixin, BaseTable):
224
224
  name = tables.TemplateColumn(template_code=DEVICE_LINK)
225
- status = ColoredLabelColumn()
226
225
  tenant = TenantColumn()
227
226
  location = tables.Column(linkify=True)
228
227
  rack = tables.Column(linkify=True)
229
- role = tables.Column(verbose_name="Role")
230
228
  device_type = tables.Column(verbose_name="Type")
231
229
 
232
230
  class Meta(BaseTable.Meta):
@@ -1333,15 +1331,13 @@ class SoftwareVersionTable(StatusTableMixin, BaseTable):
1333
1331
  )
1334
1332
 
1335
1333
 
1336
- class ControllerTable(BaseTable):
1334
+ class ControllerTable(StatusTableMixin, RoleTableMixin, BaseTable):
1337
1335
  """Table for list view."""
1338
1336
 
1339
1337
  pk = ToggleColumn()
1340
1338
  name = tables.Column(linkify=True)
1341
- status = ColoredLabelColumn()
1342
1339
  location = tables.Column(linkify=True)
1343
1340
  platform = tables.Column(linkify=True)
1344
- role = tables.Column(linkify=True)
1345
1341
  tenant = TenantColumn()
1346
1342
  external_integration = tables.Column(linkify=True)
1347
1343
  controller_device = tables.Column(linkify=True)
@@ -20,7 +20,7 @@
20
20
  </tr>
21
21
  <tr>
22
22
  <td>Role</td>
23
- <td>{{ object.role|hyperlinked_object }}</td>
23
+ <td>{{ object.role|hyperlinked_object_with_color }}</td>
24
24
  </tr>
25
25
  <tr>
26
26
  <td>Location</td>
@@ -58,7 +58,7 @@
58
58
  <span class="hover_copy">
59
59
  <h1>
60
60
  <span id="devicename">{% block title %}{{ object }}{% endblock title %}</span>
61
- <button class="btn btn-xs btn-default hover_copy_button" data-clipboard-target="#devicename">
61
+ <button class="btn btn-xs btn-default hover_copy_button" data-clipboard-text="{{ object }}">
62
62
  <span class="mdi mdi-content-copy"></span>
63
63
  </button>
64
64
  </h1>
@@ -1701,6 +1701,7 @@ class DeviceTestCase(
1701
1701
  ("front_ports", "front_ports__id"),
1702
1702
  ("interfaces", "interfaces__id"),
1703
1703
  ("interfaces", "interfaces__name"),
1704
+ ("ip_addresses", "interfaces__ip_addresses__id"),
1704
1705
  ("mac_address", "interfaces__mac_address"),
1705
1706
  ("manufacturer", "device_type__manufacturer__id"),
1706
1707
  ("manufacturer", "device_type__manufacturer__name"),
@@ -1874,6 +1875,14 @@ class DeviceTestCase(
1874
1875
  Device.objects.filter(primary_ip4__isnull=True, primary_ip6__isnull=True),
1875
1876
  )
1876
1877
 
1878
+ def test_ip_addresses(self):
1879
+ addresses = list(IPAddress.objects.filter(interfaces__isnull=False)[:2])
1880
+ params = {"ip_addresses": [addresses[0].address, addresses[1].id]}
1881
+ self.assertQuerysetEqualAndNotEmpty(
1882
+ self.filterset(params, self.queryset).qs,
1883
+ self.queryset.filter(interfaces__ip_addresses__in=addresses).distinct(),
1884
+ )
1885
+
1877
1886
  def test_virtual_chassis_member(self):
1878
1887
  # TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
1879
1888
  with self.subTest():
@@ -2168,6 +2177,7 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
2168
2177
  ("child_interfaces", "child_interfaces__name"),
2169
2178
  ("description",),
2170
2179
  # ("device", "device__id"), # TODO - InterfaceFilterSet overrides device as a MultiValueCharFilter on name only
2180
+ ("ip_addresses", "ip_addresses__id"),
2171
2181
  ("label",),
2172
2182
  ("lag", "lag__id"),
2173
2183
  ("lag", "lag__name"),
@@ -2413,6 +2423,21 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
2413
2423
  status=interface_statuses[3],
2414
2424
  )
2415
2425
 
2426
+ ipaddr_status = Status.objects.get_for_model(IPAddress).first()
2427
+ prefix_status = Status.objects.get_for_model(Prefix).first()
2428
+ namespace = Namespace.objects.first()
2429
+ Prefix.objects.create(prefix="192.0.2.0/24", namespace=namespace, status=prefix_status)
2430
+ Prefix.objects.create(prefix="2600::/64", namespace=namespace, status=prefix_status)
2431
+ ipaddresses = (
2432
+ IPAddress.objects.create(address="192.0.2.1/24", namespace=namespace, status=ipaddr_status),
2433
+ IPAddress.objects.create(address="192.0.2.2/24", namespace=namespace, status=ipaddr_status),
2434
+ IPAddress.objects.create(address="2600::1/120", namespace=namespace, status=ipaddr_status),
2435
+ IPAddress.objects.create(address="2600::0100/120", namespace=namespace, status=ipaddr_status),
2436
+ )
2437
+
2438
+ cabled_interfaces[0].add_ip_addresses([ipaddresses[0], ipaddresses[2]])
2439
+ cabled_interfaces[1].add_ip_addresses([ipaddresses[1], ipaddresses[3]])
2440
+
2416
2441
  def test_enabled(self):
2417
2442
  # TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
2418
2443
  with self.subTest():
@@ -2646,6 +2671,14 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
2646
2671
  with self.subTest("device (pk) filter with an invalid uuid"):
2647
2672
  self.assertFalse(self.filterset({"device": [uuid.uuid4()]}, self.queryset).is_valid())
2648
2673
 
2674
+ def test_ip_addresses(self):
2675
+ addresses = list(IPAddress.objects.filter(interfaces__isnull=False)[:2])
2676
+ params = {"ip_addresses": [addresses[0].address, addresses[1].id]}
2677
+ self.assertQuerysetEqualAndNotEmpty(
2678
+ self.filterset(params, self.queryset).qs,
2679
+ self.queryset.filter(ip_addresses__in=addresses).distinct(),
2680
+ )
2681
+
2649
2682
  def test_kind(self):
2650
2683
  # TODO: Not a generic_filter_test because this is a single-value filter
2651
2684
  # 2.0 TODO: Support filtering for multiple values
@@ -130,6 +130,7 @@ from nautobot.ipam.choices import IPAddressTypeChoices
130
130
  from nautobot.ipam.models import IPAddress, Namespace, Prefix, VLAN, VLANGroup, VRF
131
131
  from nautobot.tenancy.models import Tenant
132
132
  from nautobot.users.models import ObjectPermission
133
+ from nautobot.virtualization.models import Cluster, ClusterType
133
134
 
134
135
  # Use the proper swappable User model
135
136
  User = get_user_model()
@@ -2047,6 +2048,9 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2047
2048
 
2048
2049
  rack_group = RackGroup.objects.create(location=locations[0], name="Rack Group 1")
2049
2050
 
2051
+ cluster_type = ClusterType.objects.create(name="Cluster Type 1")
2052
+ cluster = Cluster.objects.create(name="Cluster 1", cluster_type=cluster_type)
2053
+
2050
2054
  rack_status = Status.objects.get_for_model(Rack).first()
2051
2055
  racks = (
2052
2056
  Rack.objects.create(
@@ -2218,6 +2222,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2218
2222
  "status": statuses[2].pk,
2219
2223
  "location": locations[1].pk,
2220
2224
  "rack": racks[1].pk,
2225
+ "cluster": cluster.pk,
2226
+ "comments": "An older device",
2221
2227
  "position": None,
2222
2228
  "face": DeviceFaceChoices.FACE_FRONT,
2223
2229
  "secrets_group": secrets_groups[1].pk,
@@ -270,6 +270,7 @@ class ContactAssociationSerializer(NautobotModelSerializer):
270
270
 
271
271
 
272
272
  class ContentTypeSerializer(BaseModelSerializer):
273
+ id = serializers.IntegerField(read_only=True)
273
274
  url = serializers.HyperlinkedIdentityField(view_name="extras-api:contenttype-detail")
274
275
  display = serializers.SerializerMethodField()
275
276
 
@@ -17,6 +17,7 @@ from rest_framework.permissions import IsAuthenticated
17
17
  from rest_framework.response import Response
18
18
 
19
19
  from nautobot.core.api.authentication import TokenPermissions
20
+ from nautobot.core.api.parsers import NautobotCSVParser
20
21
  from nautobot.core.api.utils import get_serializer_for_model
21
22
  from nautobot.core.api.views import (
22
23
  BulkDestroyModelMixin,
@@ -484,6 +485,7 @@ class ImageAttachmentViewSet(ModelViewSet):
484
485
  queryset = ImageAttachment.objects.all()
485
486
  serializer_class = serializers.ImageAttachmentSerializer
486
487
  filterset_class = filters.ImageAttachmentFilterSet
488
+ parser_classes = [JSONParser, NautobotCSVParser, MultiPartParser]
487
489
 
488
490
 
489
491
  #
@@ -1682,6 +1682,8 @@ class RoleBulkEditForm(NautobotBulkEditForm):
1682
1682
 
1683
1683
  pk = forms.ModelMultipleChoiceField(queryset=Role.objects.all(), widget=forms.MultipleHiddenInput)
1684
1684
  color = forms.CharField(max_length=6, required=False, widget=ColorSelect())
1685
+ description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
1686
+ weight = forms.IntegerField(required=False)
1685
1687
  content_types = MultipleContentTypeField(
1686
1688
  queryset=RoleModelsQuery().as_queryset(), required=False, label="Content Type(s)"
1687
1689
  )
@@ -0,0 +1,42 @@
1
+ """Additional functions to process an OAuth2/OIDC user."""
2
+
3
+ import logging
4
+
5
+ from django.conf import settings
6
+ from django.contrib.auth.models import Group
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ CLAIMS_GROUP_NAME = getattr(settings, "SSO_CLAIMS_GROUP", "groups")
12
+ """ Which claim to look at in the OAuth2/OIDC response
13
+
14
+ For Okta you can look at `Okta -> Authorization Servers -> Claims`. And a reasonable
15
+ default is "groups". For Azure a reasonable default is "roles".
16
+ """
17
+
18
+ SUPERUSER_GROUPS = getattr(settings, "SSO_SUPERUSER_GROUPS", [])
19
+ STAFF_GROUPS = getattr(settings, "SSO_STAFF_GROUPS", [])
20
+
21
+
22
+ def group_sync(uid, user=None, response=None, *args, **kwargs):
23
+ """Sync the users groups from OAuth2/OIDC auth and set staff/superuser as appropriate."""
24
+ if user and response and CLAIMS_GROUP_NAME and response.get(CLAIMS_GROUP_NAME, False):
25
+ group_memberships = response.get(CLAIMS_GROUP_NAME)
26
+ is_staff = False
27
+ is_superuser = False
28
+ logger.debug(f"User {uid} is a member of {', '.join(group_memberships)}")
29
+ # Make sure all groups exist in Nautobot
30
+ group_ids = []
31
+ for group in group_memberships:
32
+ if group in SUPERUSER_GROUPS:
33
+ is_superuser = True
34
+ if group in STAFF_GROUPS:
35
+ is_staff = True
36
+ group_ids.append(Group.objects.get_or_create(name=group)[0].id)
37
+ user.groups.set(group_ids)
38
+ user.is_superuser = is_superuser
39
+ user.is_staff = is_staff
40
+ user.save()
41
+ else:
42
+ logger.debug(f"Did not receive groups from OAuth2/OIDC, response: {response}")
@@ -201,6 +201,7 @@ class ObjectMetadata(ChangeLoggedModel, BaseModel):
201
201
  objects = ObjectMetadataManager()
202
202
  natural_key_field_names = ["pk"]
203
203
  documentation_static_path = "docs/user-guide/platform-functionality/objectmetadata.html"
204
+ is_metadata_associable_model = False
204
205
 
205
206
  class Meta:
206
207
  ordering = ["metadata_type"]
@@ -831,7 +831,7 @@ class Note(ChangeLoggedModel, BaseModel):
831
831
  unique_together = [["assigned_object_type", "assigned_object_id", "user_name", "created"]]
832
832
 
833
833
  def __str__(self):
834
- return f"{self.assigned_object} - {self.created.isoformat()}"
834
+ return f"{self.assigned_object} - {self.created.isoformat() if self.created else None}"
835
835
 
836
836
  def save(self, *args, **kwargs):
837
837
  # Record the user's name as static strings
@@ -207,8 +207,9 @@ class NautobotAppConfig(NautobotConfig):
207
207
  override_views = import_object(f"{self.__module__}.{self.override_views}")
208
208
  if override_views is not None:
209
209
  for qualified_view_name, view in override_views.items():
210
+ view_class_name = view.view_class.__name__ if hasattr(view, "view_class") else view.cls.__name__
210
211
  self.features.setdefault("overridden_views", []).append(
211
- (qualified_view_name, f"{view.__module__}.{view.view_class.__name__}")
212
+ (qualified_view_name, f"{view.__module__}.{view_class_name}")
212
213
  )
213
214
  register_override_views(override_views, self.name)
214
215
 
@@ -518,6 +519,7 @@ class TableExtension:
518
519
  """
519
520
 
520
521
  model = None
522
+ suffix = None
521
523
  table_columns = {}
522
524
  add_to_default_columns = ()
523
525
  remove_from_default_columns = ()
@@ -593,7 +595,7 @@ def _add_columns_into_model_table(table_extension, app_name):
593
595
  logger.error(error)
594
596
  return
595
597
 
596
- table = get_table_for_model(table_extension.model)
598
+ table = get_table_for_model(table_extension.model, suffix=table_extension.suffix)
597
599
  for name, column in table_extension.table_columns.items():
598
600
  _validate_table_column_name_is_prefixed_with_app_name(name, app_name)
599
601
  _add_column_to_table_base_columns(table, name, column, app_name)
@@ -628,18 +630,28 @@ def _modify_default_table_columns(table_extension, app_name):
628
630
  """Add or remove columns from the table default columns."""
629
631
  from nautobot.core.utils.lookup import get_table_for_model
630
632
 
631
- table = get_table_for_model(table_extension.model)
633
+ table = get_table_for_model(table_extension.model, suffix=table_extension.suffix)
632
634
  message = (
633
635
  f"{app_name}: Cannot {{action}} column `{{column_name}}` {{preposition}} the default columns for `{table}`."
634
636
  )
635
637
 
636
638
  for column_name in table_extension.add_to_default_columns:
639
+ if not getattr(table.Meta, "default_columns", None):
640
+ logger.warning(
641
+ f"{app_name}: Table `{table}` does not have a `default_columns` attribute. Cannot add column: {column_name}."
642
+ )
643
+ continue
637
644
  if column_name in table.base_columns:
638
645
  table.Meta.default_columns = (*table.Meta.default_columns, column_name)
639
646
  else:
640
647
  logger.debug(message.format(action="add", column_name=column_name, preposition="to"))
641
648
 
642
649
  for column_name in table_extension.remove_from_default_columns:
650
+ if not getattr(table.Meta, "default_columns", None):
651
+ logger.warning(
652
+ f"{app_name}: Table `{table}` does not have a `default_columns` attribute. Cannot remove column: {column_name}."
653
+ )
654
+ continue
643
655
  if column_name in table.Meta.default_columns:
644
656
  table.Meta.default_columns = tuple(name for name in table.Meta.default_columns if name != column_name)
645
657
  else:
nautobot/extras/tables.py CHANGED
@@ -978,6 +978,7 @@ class MetadataTypeTable(BaseTable):
978
978
 
979
979
  class ObjectMetadataTable(BaseTable):
980
980
  pk = ToggleColumn()
981
+ # NOTE: there is no identity column in this table; this is intentional as we have no detail view for ObjectMetadata
981
982
  metadata_type = tables.Column(linkify=True)
982
983
  assigned_object = tables.TemplateColumn(
983
984
  template_code=ASSIGNED_OBJECT, verbose_name="Assigned object", orderable=False
@@ -28,7 +28,7 @@
28
28
  </th>
29
29
  </tr>
30
30
  {% endifchanged %}
31
- <tr class="collapseme-{{ row.record.grouping|slugify }}{% if not perms.extras.run_job or not row.record.runnable %} disabled{% endif %} collapse in" data-parent="#accordion" {{ row.attrs.as_html }}>
31
+ <tr class="{% cycle 'even' 'odd' %} collapseme-{{ row.record.grouping|slugify }}{% if not perms.extras.run_job or not row.record.runnable %} disabled{% endif %} collapse in" data-parent="#accordion" {{ row.attrs.as_html }}>
32
32
  {% for column, cell in row.items %}
33
33
  <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
34
34
  {% endfor %}
@@ -3033,8 +3033,6 @@ class ObjectChangeTestCase(TestCase):
3033
3033
 
3034
3034
 
3035
3035
  class ObjectMetadataTestCase(
3036
- ViewTestCases.GetObjectViewTestCase,
3037
- ViewTestCases.GetObjectChangelogViewTestCase,
3038
3036
  ViewTestCases.ListObjectsViewTestCase,
3039
3037
  ):
3040
3038
  model = ObjectMetadata
@@ -3609,6 +3607,8 @@ class RoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
3609
3607
 
3610
3608
  cls.bulk_edit_data = {
3611
3609
  "color": "000000",
3610
+ "description": "I used to be a new role object.",
3611
+ "weight": 255,
3612
3612
  }
3613
3613
 
3614
3614
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
nautobot/extras/views.py CHANGED
@@ -2228,8 +2228,6 @@ class MetadataTypeUIViewSet(NautobotUIViewSet):
2228
2228
 
2229
2229
 
2230
2230
  class ObjectMetadataUIViewSet(
2231
- ObjectChangeLogViewMixin,
2232
- ObjectDetailViewMixin,
2233
2231
  ObjectListViewMixin,
2234
2232
  ):
2235
2233
  filterset_class = filters.ObjectMetadataFilterSet
nautobot/ipam/lookups.py CHANGED
@@ -3,7 +3,9 @@ from django.db.models import Lookup, lookups
3
3
  import netaddr
4
4
 
5
5
 
6
- def _mysql_varbin_to_broadcast():
6
+ def _mysql_varbin_to_broadcast(alias=None):
7
+ if alias:
8
+ return f"HEX({alias}.broadcast)"
7
9
  return "HEX(broadcast)"
8
10
 
9
11
 
@@ -13,11 +15,15 @@ def _mysql_varbin_to_hex(lhs, alias=None):
13
15
  return f"HEX({lhs})"
14
16
 
15
17
 
16
- def _mysql_varbin_to_network():
18
+ def _mysql_varbin_to_network(alias=None):
19
+ if alias:
20
+ return f"HEX({alias}.network)"
17
21
  return "HEX(network)"
18
22
 
19
23
 
20
- def _postgresql_varbin_to_broadcast(length):
24
+ def _postgresql_varbin_to_broadcast(length, alias=None):
25
+ if alias:
26
+ return f"right({alias}.broadcast::text, -1)::varbit::bit({length})"
21
27
  return f"right(broadcast::text, -1)::varbit::bit({length})"
22
28
 
23
29
 
@@ -27,8 +33,10 @@ def _postgresql_varbin_to_integer(lhs, length, alias=None):
27
33
  return f"right({lhs}::text, -1)::varbit::bit({length})"
28
34
 
29
35
 
30
- def _postgresql_varbin_to_network(lhs, length):
36
+ def _postgresql_varbin_to_network(lhs, length, alias=None):
31
37
  # convert to bitstring, 0 out everything larger than prefix_length
38
+ if alias:
39
+ return f"lpad(right({alias}.{lhs}::text, -1)::varbit::text, {alias}.prefix_length, '0')::bit({length})"
32
40
  return f"lpad(right({lhs}::text, -1)::varbit::text, prefix_length, '0')::bit({length})"
33
41
 
34
42
 
@@ -52,8 +60,8 @@ def get_ip_info(field_name, ip_str, alias=None):
52
60
  ip_details.rhs = py_to_hex(ip.ip, ip_details.length)
53
61
  ip_details.net_addr = f"'{py_to_hex(ip.network, ip_details.length)}'"
54
62
  ip_details.bcast_addr = f"'{py_to_hex(ip[-1], ip_details.length)}'"
55
- ip_details.q_net = _mysql_varbin_to_network()
56
- ip_details.q_bcast = _mysql_varbin_to_broadcast()
63
+ ip_details.q_net = _mysql_varbin_to_network(alias=alias)
64
+ ip_details.q_bcast = _mysql_varbin_to_broadcast(alias=alias)
57
65
  ip_details.q_ip = _mysql_varbin_to_hex(field_name, alias=alias)
58
66
 
59
67
  elif _connection.vendor == "postgresql":
@@ -61,8 +69,8 @@ def get_ip_info(field_name, ip_str, alias=None):
61
69
  ip_details.addr_str = f"B'{bin(int(ip_details.addr))[2:].zfill(ip_details.length)}'"
62
70
  ip_details.net_addr = f"B'{bin(int(ip.network))[2:].zfill(ip_details.length)}'"
63
71
  ip_details.bcast_addr = f"B'{bin(int(ip[-1]))[2:].zfill(ip_details.length)}'"
64
- ip_details.q_net = _postgresql_varbin_to_network(field_name, ip_details.length)
65
- ip_details.q_bcast = _postgresql_varbin_to_broadcast(ip_details.length)
72
+ ip_details.q_net = _postgresql_varbin_to_network(field_name, ip_details.length, alias=alias)
73
+ ip_details.q_bcast = _postgresql_varbin_to_broadcast(ip_details.length, alias=alias)
66
74
  ip_details.q_ip = _postgresql_varbin_to_integer(field_name, ip_details.length, alias=alias)
67
75
 
68
76
  return ip_details
@@ -71,25 +79,38 @@ def get_ip_info(field_name, ip_str, alias=None):
71
79
  class IPDetails:
72
80
  """Class for setting up all details about an IP they may be needed"""
73
81
 
74
- net = None
75
- addr = None
76
- ip = None
77
- prefix = None
78
- length = None
79
- addr_str = None
80
- rhs = None
81
- net_addr = None
82
- bcast_addr = None
83
- q_net = None
84
- q_bcast = None
85
- q_ip = None
82
+ addr = None # 10.0.0.0
83
+ ip = None # 10.0.0.0/8
84
+ prefix = None # 8
85
+ length = None # 32
86
+ addr_str = None # B'00001010000000000000000000000000'
87
+ rhs = None # 00001010000000000000000000000000
88
+ net_addr = None # B'00001010000000000000000000000000'
89
+ bcast_addr = None # B'00001010111111111111111111111111'
90
+ q_net = None # mysql or postgres specific
91
+ q_bcast = None # mysql or postgres specific
92
+ q_ip = None # mysql or postgres specific
86
93
  to_len = {4: 32, 6: 128}
87
94
 
95
+ def __str__(self):
96
+ return f"""\
97
+ addr: {self.addr}
98
+ ip: {self.ip}
99
+ prefix: {self.prefix}
100
+ length: {self.length}
101
+ addr_str: {self.addr_str}
102
+ rhs: {self.rhs}
103
+ net_addr: {self.net_addr}
104
+ bcast_addr: {self.bcast_addr}
105
+ q_net: {self.q_net}
106
+ q_bcast: {self.q_bcast}
107
+ q_ip: {self.q_ip}"""
108
+
88
109
 
89
110
  class StringMatchMixin:
90
- def process_lhs(self, qn, connection, lhs=None):
111
+ def process_lhs(self, compiler, connection, lhs=None):
91
112
  lhs = lhs or self.lhs
92
- lhs_string, lhs_params = qn.compile(lhs)
113
+ lhs_string, lhs_params = compiler.compile(lhs)
93
114
  if connection.vendor == "postgresql":
94
115
  raise NotSupportedError("Lookup not supported on postgresql.")
95
116
  return f"INET6_NTOA({lhs_string})", lhs_params
@@ -129,6 +150,7 @@ class IRegex(StringMatchMixin, lookups.IRegex):
129
150
 
130
151
  class NetworkFieldMixin:
131
152
  def get_prep_lookup(self):
153
+ self.alias = self.lhs.alias
132
154
  field_name = self.lhs.field.name
133
155
  if field_name not in ["host", "network"]:
134
156
  raise NotSupportedError(f"Lookup only provided on the host and network fields, not {field_name}.")
@@ -139,8 +161,8 @@ class NetworkFieldMixin:
139
161
  self.ip = get_ip_info(field_name, self.rhs, alias=self.lhs.alias)
140
162
  return str(self.ip.ip)
141
163
 
142
- def process_rhs(self, qn, connection):
143
- sql, params = super().process_rhs(qn, connection)
164
+ def process_rhs(self, compiler, connection):
165
+ sql, params = super().process_rhs(compiler, connection)
144
166
  params[0] = self.ip.rhs
145
167
  return sql, params
146
168
 
@@ -148,50 +170,67 @@ class NetworkFieldMixin:
148
170
  class NetEquals(NetworkFieldMixin, Lookup):
149
171
  lookup_name = "net_equals"
150
172
 
151
- def as_sql(self, qn, connection):
152
- _, lhs_params = self.process_lhs(qn, connection)
153
- rhs, rhs_params = self.process_rhs(qn, connection)
154
- query = f"prefix_length = {self.ip.prefix} AND {rhs} = {self.ip.q_ip}"
173
+ def as_sql(self, compiler, connection):
174
+ _, lhs_params = self.process_lhs(compiler, connection)
175
+ rhs, rhs_params = self.process_rhs(compiler, connection)
176
+ if self.alias:
177
+ query = f"{self.alias}.prefix_length = {self.ip.prefix} AND {rhs} = {self.ip.q_ip}"
178
+ else:
179
+ query = f"prefix_length = {self.ip.prefix} AND {rhs} = {self.ip.q_ip}"
155
180
  return query, lhs_params + rhs_params
156
181
 
157
182
 
158
183
  class NetContainsOrEquals(NetworkFieldMixin, Lookup):
159
184
  lookup_name = "net_contains_or_equals"
160
185
 
161
- def as_sql(self, qn, connection):
162
- _, lhs_params = self.process_lhs(qn, connection)
163
- rhs, rhs_params = self.process_rhs(qn, connection)
164
- query = f"prefix_length <= {self.ip.prefix} AND {rhs} BETWEEN {self.ip.q_net} AND {self.ip.q_bcast}"
186
+ def as_sql(self, compiler, connection):
187
+ _, lhs_params = self.process_lhs(compiler, connection)
188
+ rhs, rhs_params = self.process_rhs(compiler, connection)
189
+ if self.alias:
190
+ query = f"{self.alias}.prefix_length <= {self.ip.prefix} AND {rhs} BETWEEN {self.ip.q_net} AND {self.ip.q_bcast}"
191
+ else:
192
+ query = f"prefix_length <= {self.ip.prefix} AND {rhs} BETWEEN {self.ip.q_net} AND {self.ip.q_bcast}"
165
193
  return query, lhs_params + rhs_params
166
194
 
167
195
 
168
196
  class NetContains(NetworkFieldMixin, Lookup):
169
197
  lookup_name = "net_contains"
170
198
 
171
- def as_sql(self, qn, connection):
172
- _, lhs_params = self.process_lhs(qn, connection)
173
- rhs, rhs_params = self.process_rhs(qn, connection)
174
- query = f"prefix_length < {self.ip.prefix} AND {rhs} BETWEEN {self.ip.q_net} AND {self.ip.q_bcast}"
199
+ def as_sql(self, compiler, connection):
200
+ _, lhs_params = self.process_lhs(compiler, connection)
201
+ rhs, rhs_params = self.process_rhs(compiler, connection)
202
+ if self.alias:
203
+ query = (
204
+ f"{self.alias}.prefix_length < {self.ip.prefix} AND {rhs} BETWEEN {self.ip.q_net} AND {self.ip.q_bcast}"
205
+ )
206
+ else:
207
+ query = f"prefix_length < {self.ip.prefix} AND {rhs} BETWEEN {self.ip.q_net} AND {self.ip.q_bcast}"
175
208
  return query, lhs_params + rhs_params
176
209
 
177
210
 
178
211
  class NetContainedOrEqual(NetworkFieldMixin, Lookup):
179
212
  lookup_name = "net_contained_or_equal"
180
213
 
181
- def as_sql(self, qn, connection):
182
- _, lhs_params = self.process_lhs(qn, connection)
183
- rhs, rhs_params = self.process_rhs(qn, connection)
184
- query = f"prefix_length >= {self.ip.prefix} AND {self.ip.q_net} BETWEEN {rhs} AND {self.ip.bcast_addr}"
214
+ def as_sql(self, compiler, connection):
215
+ _, lhs_params = self.process_lhs(compiler, connection)
216
+ rhs, rhs_params = self.process_rhs(compiler, connection)
217
+ if self.alias:
218
+ query = f"{self.alias}.prefix_length >= {self.ip.prefix} AND {self.ip.q_net} BETWEEN {rhs} AND {self.ip.bcast_addr}"
219
+ else:
220
+ query = f"prefix_length >= {self.ip.prefix} AND {self.ip.q_net} BETWEEN {rhs} AND {self.ip.bcast_addr}"
185
221
  return query, lhs_params + rhs_params
186
222
 
187
223
 
188
224
  class NetContained(NetworkFieldMixin, Lookup):
189
225
  lookup_name = "net_contained"
190
226
 
191
- def as_sql(self, qn, connection):
192
- _, lhs_params = self.process_lhs(qn, connection)
193
- rhs, rhs_params = self.process_rhs(qn, connection)
194
- query = f"prefix_length > {self.ip.prefix} AND {self.ip.q_net} BETWEEN {rhs} AND {self.ip.bcast_addr}"
227
+ def as_sql(self, compiler, connection):
228
+ _, lhs_params = self.process_lhs(compiler, connection)
229
+ rhs, rhs_params = self.process_rhs(compiler, connection)
230
+ if self.alias:
231
+ query = f"{self.alias}.prefix_length > {self.ip.prefix} AND {self.ip.q_net} BETWEEN {rhs} AND {self.ip.bcast_addr}"
232
+ else:
233
+ query = f"prefix_length > {self.ip.prefix} AND {self.ip.q_net} BETWEEN {rhs} AND {self.ip.bcast_addr}"
195
234
  return query, lhs_params + rhs_params
196
235
 
197
236
 
@@ -205,19 +244,19 @@ class NetHost(Lookup):
205
244
  self.ip = get_ip_info(field_name, self.rhs, alias=self.lhs.alias)
206
245
  return str(self.ip.ip)
207
246
 
208
- def process_rhs(self, qn, connection):
209
- sql, params = super().process_rhs(qn, connection)
247
+ def process_rhs(self, compiler, connection):
248
+ sql, params = super().process_rhs(compiler, connection)
210
249
  params[0] = self.ip.rhs
211
250
  return sql, params
212
251
 
213
- def process_lhs(self, qn, connection, lhs=None):
252
+ def process_lhs(self, compiler, connection, lhs=None):
214
253
  lhs = lhs or self.lhs
215
- _, lhs_params = qn.compile(lhs)
254
+ _, lhs_params = compiler.compile(lhs)
216
255
  return self.ip.q_ip, lhs_params
217
256
 
218
- def as_sql(self, qn, connection):
219
- lhs, lhs_params = self.process_lhs(qn, connection)
220
- rhs, rhs_params = self.process_rhs(qn, connection)
257
+ def as_sql(self, compiler, connection):
258
+ lhs, lhs_params = self.process_lhs(compiler, connection)
259
+ rhs, rhs_params = self.process_rhs(compiler, connection)
221
260
  return f"{lhs} = {rhs}", lhs_params + rhs_params
222
261
 
223
262
 
@@ -242,9 +281,9 @@ class NetIn(Lookup):
242
281
  self.query_starter = "'1' != ANY(%s) AND "
243
282
  return self.rhs
244
283
 
245
- def as_sql(self, qn, connection):
246
- _, lhs_params = self.process_lhs(qn, connection)
247
- _, rhs_params = self.process_rhs(qn, connection)
284
+ def as_sql(self, compiler, connection):
285
+ _, lhs_params = self.process_lhs(compiler, connection)
286
+ _, rhs_params = self.process_rhs(compiler, connection)
248
287
  query = self.query_starter
249
288
  query += "OR ".join(f"{ip.q_ip} BETWEEN {ip.net_addr} AND {ip.bcast_addr} " for ip in self.ips)
250
289
  return query, lhs_params + rhs_params
@@ -253,9 +292,9 @@ class NetIn(Lookup):
253
292
  class NetHostContained(NetworkFieldMixin, Lookup):
254
293
  lookup_name = "net_host_contained"
255
294
 
256
- def as_sql(self, qn, connection):
257
- _, lhs_params = self.process_lhs(qn, connection)
258
- rhs, rhs_params = self.process_rhs(qn, connection)
295
+ def as_sql(self, compiler, connection):
296
+ _, lhs_params = self.process_lhs(compiler, connection)
297
+ rhs, rhs_params = self.process_rhs(compiler, connection)
259
298
  query = f"{self.ip.q_ip} BETWEEN {rhs} AND {self.ip.bcast_addr}"
260
299
  return query, lhs_params + rhs_params
261
300
 
@@ -270,12 +309,12 @@ class NetFamily(Lookup):
270
309
  self.rhs = 16
271
310
  return self.rhs
272
311
 
273
- def process_lhs(self, qn, connection, lhs=None):
312
+ def process_lhs(self, compiler, connection, lhs=None):
274
313
  lhs = lhs or self.lhs
275
- lhs_string, lhs_params = qn.compile(lhs)
314
+ lhs_string, lhs_params = compiler.compile(lhs)
276
315
  return f"LENGTH({lhs_string})", lhs_params
277
316
 
278
- def as_sql(self, qn, connection):
279
- lhs, lhs_params = self.process_lhs(qn, connection)
280
- rhs, rhs_params = self.process_rhs(qn, connection)
317
+ def as_sql(self, compiler, connection):
318
+ lhs, lhs_params = self.process_lhs(compiler, connection)
319
+ rhs, rhs_params = self.process_rhs(compiler, connection)
281
320
  return f"{lhs} = {rhs}", lhs_params + rhs_params