Selaa lähdekoodia

Closes #16224 GraphQL Pagination (#18903)

* 16244 add pagination

* 16244 add pagination

* 16244 fix order_by pagination

* 16224 document pagination

* 16224 remove extraneous code

* 16224 missing core types

* 16224 review changes

* 16224 review changes

* 16224 review changes
Arthur Hanson 11 kuukautta sitten
vanhempi
commit
fe7cc8cae9

+ 12 - 0
docs/integrations/graphql-api.md

@@ -131,6 +131,18 @@ Certain queries can return multiple types of objects, for example cable terminat
 ```
 The field "class_type" is an easy way to distinguish what type of object it is when viewing the returned data, or when filtering.  It contains the class name, for example "CircuitTermination" or "ConsoleServerPort".
 
+## Pagination
+
+Queries can be paginated by specifying pagination in the query and supplying an offset and optionaly a limit in the query.  If no limit is given, a default of 100 is used.  Queries are not paginated unless requested in the query. An example paginated query is shown below:
+
+```
+query {
+  device_list(pagination: { offset: 0, limit: 20 }) {
+    id
+  }
+}
+```
+
 ## Authentication
 
 NetBox's GraphQL API uses the same API authentication tokens as its REST API. Authentication tokens are included with requests by attaching an `Authorization` HTTP header in the following form:

+ 22 - 11
netbox/circuits/graphql/types.py

@@ -32,7 +32,8 @@ __all__ = (
 @strawberry_django.type(
     models.Provider,
     fields='__all__',
-    filters=ProviderFilter
+    filters=ProviderFilter,
+    pagination=True
 )
 class ProviderType(NetBoxObjectType, ContactsMixin):
 
@@ -45,7 +46,8 @@ class ProviderType(NetBoxObjectType, ContactsMixin):
 @strawberry_django.type(
     models.ProviderAccount,
     fields='__all__',
-    filters=ProviderAccountFilter
+    filters=ProviderAccountFilter,
+    pagination=True
 )
 class ProviderAccountType(NetBoxObjectType):
     provider: Annotated["ProviderType", strawberry.lazy('circuits.graphql.types')]
@@ -56,7 +58,8 @@ class ProviderAccountType(NetBoxObjectType):
 @strawberry_django.type(
     models.ProviderNetwork,
     fields='__all__',
-    filters=ProviderNetworkFilter
+    filters=ProviderNetworkFilter,
+    pagination=True
 )
 class ProviderNetworkType(NetBoxObjectType):
     provider: Annotated["ProviderType", strawberry.lazy('circuits.graphql.types')]
@@ -67,7 +70,8 @@ class ProviderNetworkType(NetBoxObjectType):
 @strawberry_django.type(
     models.CircuitTermination,
     exclude=['termination_type', 'termination_id', '_location', '_region', '_site', '_site_group', '_provider_network'],
-    filters=CircuitTerminationFilter
+    filters=CircuitTerminationFilter,
+    pagination=True
 )
 class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, ObjectType):
     circuit: Annotated["CircuitType", strawberry.lazy('circuits.graphql.types')]
@@ -86,7 +90,8 @@ class CircuitTerminationType(CustomFieldsMixin, TagsMixin, CabledObjectMixin, Ob
 @strawberry_django.type(
     models.CircuitType,
     fields='__all__',
-    filters=CircuitTypeFilter
+    filters=CircuitTypeFilter,
+    pagination=True
 )
 class CircuitTypeType(OrganizationalObjectType):
     color: str
@@ -97,7 +102,8 @@ class CircuitTypeType(OrganizationalObjectType):
 @strawberry_django.type(
     models.Circuit,
     fields='__all__',
-    filters=CircuitFilter
+    filters=CircuitFilter,
+    pagination=True
 )
 class CircuitType(NetBoxObjectType, ContactsMixin):
     provider: ProviderType
@@ -113,7 +119,8 @@ class CircuitType(NetBoxObjectType, ContactsMixin):
 @strawberry_django.type(
     models.CircuitGroup,
     fields='__all__',
-    filters=CircuitGroupFilter
+    filters=CircuitGroupFilter,
+    pagination=True
 )
 class CircuitGroupType(OrganizationalObjectType):
     tenant: TenantType | None
@@ -122,7 +129,8 @@ class CircuitGroupType(OrganizationalObjectType):
 @strawberry_django.type(
     models.CircuitGroupAssignment,
     exclude=['member_type', 'member_id'],
-    filters=CircuitGroupAssignmentFilter
+    filters=CircuitGroupAssignmentFilter,
+    pagination=True
 )
 class CircuitGroupAssignmentType(TagsMixin, BaseObjectType):
     group: Annotated["CircuitGroupType", strawberry.lazy('circuits.graphql.types')]
@@ -138,7 +146,8 @@ class CircuitGroupAssignmentType(TagsMixin, BaseObjectType):
 @strawberry_django.type(
     models.VirtualCircuitType,
     fields='__all__',
-    filters=VirtualCircuitTypeFilter
+    filters=VirtualCircuitTypeFilter,
+    pagination=True
 )
 class VirtualCircuitTypeType(OrganizationalObjectType):
     color: str
@@ -149,7 +158,8 @@ class VirtualCircuitTypeType(OrganizationalObjectType):
 @strawberry_django.type(
     models.VirtualCircuitTermination,
     fields='__all__',
-    filters=VirtualCircuitTerminationFilter
+    filters=VirtualCircuitTerminationFilter,
+    pagination=True
 )
 class VirtualCircuitTerminationType(CustomFieldsMixin, TagsMixin, ObjectType):
     virtual_circuit: Annotated[
@@ -165,7 +175,8 @@ class VirtualCircuitTerminationType(CustomFieldsMixin, TagsMixin, ObjectType):
 @strawberry_django.type(
     models.VirtualCircuit,
     fields='__all__',
-    filters=VirtualCircuitFilter
+    filters=VirtualCircuitFilter,
+    pagination=True
 )
 class VirtualCircuitType(NetBoxObjectType):
     provider_network: ProviderNetworkType = strawberry_django.field(select_related=["provider_network"])

+ 11 - 4
netbox/core/graphql/types.py

@@ -19,7 +19,8 @@ __all__ = (
 @strawberry_django.type(
     models.DataFile,
     exclude=['data',],
-    filters=DataFileFilter
+    filters=DataFileFilter,
+    pagination=True
 )
 class DataFileType(BaseObjectType):
     source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')]
@@ -28,7 +29,8 @@ class DataFileType(BaseObjectType):
 @strawberry_django.type(
     models.DataSource,
     fields='__all__',
-    filters=DataSourceFilter
+    filters=DataSourceFilter,
+    pagination=True
 )
 class DataSourceType(NetBoxObjectType):
 
@@ -38,12 +40,17 @@ class DataSourceType(NetBoxObjectType):
 @strawberry_django.type(
     models.ObjectChange,
     fields='__all__',
-    filters=ObjectChangeFilter
+    filters=ObjectChangeFilter,
+    pagination=True
 )
 class ObjectChangeType(BaseObjectType):
     pass
 
 
-@strawberry_django.type(DjangoContentType, fields='__all__')
+@strawberry_django.type(
+    DjangoContentType,
+    fields='__all__',
+    pagination=True
+)
 class ContentType:
     pass

+ 86 - 43
netbox/dcim/graphql/types.py

@@ -133,7 +133,8 @@ class ModularComponentTemplateType(ComponentTemplateType):
 @strawberry_django.type(
     models.CableTermination,
     exclude=['termination_type', 'termination_id', '_device', '_rack', '_location', '_site'],
-    filters=CableTerminationFilter
+    filters=CableTerminationFilter,
+    pagination=True
 )
 class CableTerminationType(NetBoxObjectType):
     cable: Annotated["CableType", strawberry.lazy('dcim.graphql.types')] | None
@@ -153,7 +154,8 @@ class CableTerminationType(NetBoxObjectType):
 @strawberry_django.type(
     models.Cable,
     fields='__all__',
-    filters=CableFilter
+    filters=CableFilter,
+    pagination=True
 )
 class CableType(NetBoxObjectType):
     color: str
@@ -189,7 +191,8 @@ class CableType(NetBoxObjectType):
 @strawberry_django.type(
     models.ConsolePort,
     exclude=['_path'],
-    filters=ConsolePortFilter
+    filters=ConsolePortFilter,
+    pagination=True
 )
 class ConsolePortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
     pass
@@ -198,7 +201,8 @@ class ConsolePortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin
 @strawberry_django.type(
     models.ConsolePortTemplate,
     fields='__all__',
-    filters=ConsolePortTemplateFilter
+    filters=ConsolePortTemplateFilter,
+    pagination=True
 )
 class ConsolePortTemplateType(ModularComponentTemplateType):
     pass
@@ -207,7 +211,8 @@ class ConsolePortTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.ConsoleServerPort,
     exclude=['_path'],
-    filters=ConsoleServerPortFilter
+    filters=ConsoleServerPortFilter,
+    pagination=True
 )
 class ConsoleServerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
     pass
@@ -216,7 +221,8 @@ class ConsoleServerPortType(ModularComponentType, CabledObjectMixin, PathEndpoin
 @strawberry_django.type(
     models.ConsoleServerPortTemplate,
     fields='__all__',
-    filters=ConsoleServerPortTemplateFilter
+    filters=ConsoleServerPortTemplateFilter,
+    pagination=True
 )
 class ConsoleServerPortTemplateType(ModularComponentTemplateType):
     pass
@@ -225,7 +231,8 @@ class ConsoleServerPortTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.Device,
     fields='__all__',
-    filters=DeviceFilter
+    filters=DeviceFilter,
+    pagination=True
 )
 class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
     console_port_count: BigInt
@@ -280,7 +287,8 @@ class DeviceType(ConfigContextMixin, ImageAttachmentsMixin, ContactsMixin, NetBo
 @strawberry_django.type(
     models.DeviceBay,
     fields='__all__',
-    filters=DeviceBayFilter
+    filters=DeviceBayFilter,
+    pagination=True
 )
 class DeviceBayType(ComponentType):
     installed_device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None
@@ -289,7 +297,8 @@ class DeviceBayType(ComponentType):
 @strawberry_django.type(
     models.DeviceBayTemplate,
     fields='__all__',
-    filters=DeviceBayTemplateFilter
+    filters=DeviceBayTemplateFilter,
+    pagination=True
 )
 class DeviceBayTemplateType(ComponentTemplateType):
     pass
@@ -298,7 +307,8 @@ class DeviceBayTemplateType(ComponentTemplateType):
 @strawberry_django.type(
     models.InventoryItemTemplate,
     exclude=['component_type', 'component_id', 'parent'],
-    filters=InventoryItemTemplateFilter
+    filters=InventoryItemTemplateFilter,
+    pagination=True
 )
 class InventoryItemTemplateType(ComponentTemplateType):
     role: Annotated["InventoryItemRoleType", strawberry.lazy('dcim.graphql.types')] | None
@@ -324,7 +334,8 @@ class InventoryItemTemplateType(ComponentTemplateType):
 @strawberry_django.type(
     models.DeviceRole,
     fields='__all__',
-    filters=DeviceRoleFilter
+    filters=DeviceRoleFilter,
+    pagination=True
 )
 class DeviceRoleType(OrganizationalObjectType):
     color: str
@@ -337,7 +348,8 @@ class DeviceRoleType(OrganizationalObjectType):
 @strawberry_django.type(
     models.DeviceType,
     fields='__all__',
-    filters=DeviceTypeFilter
+    filters=DeviceTypeFilter,
+    pagination=True
 )
 class DeviceTypeType(NetBoxObjectType):
     console_port_template_count: BigInt
@@ -371,7 +383,8 @@ class DeviceTypeType(NetBoxObjectType):
 @strawberry_django.type(
     models.FrontPort,
     fields='__all__',
-    filters=FrontPortFilter
+    filters=FrontPortFilter,
+    pagination=True
 )
 class FrontPortType(ModularComponentType, CabledObjectMixin):
     color: str
@@ -381,7 +394,8 @@ class FrontPortType(ModularComponentType, CabledObjectMixin):
 @strawberry_django.type(
     models.FrontPortTemplate,
     fields='__all__',
-    filters=FrontPortTemplateFilter
+    filters=FrontPortTemplateFilter,
+    pagination=True
 )
 class FrontPortTemplateType(ModularComponentTemplateType):
     color: str
@@ -391,7 +405,8 @@ class FrontPortTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.MACAddress,
     exclude=['assigned_object_type', 'assigned_object_id'],
-    filters=MACAddressFilter
+    filters=MACAddressFilter,
+    pagination=True
 )
 class MACAddressType(NetBoxObjectType):
     mac_address: str
@@ -407,7 +422,8 @@ class MACAddressType(NetBoxObjectType):
 @strawberry_django.type(
     models.Interface,
     exclude=['_path'],
-    filters=InterfaceFilter
+    filters=InterfaceFilter,
+    pagination=True
 )
 class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, PathEndpointMixin):
     _name: str
@@ -434,7 +450,8 @@ class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, P
 @strawberry_django.type(
     models.InterfaceTemplate,
     fields='__all__',
-    filters=InterfaceTemplateFilter
+    filters=InterfaceTemplateFilter,
+    pagination=True
 )
 class InterfaceTemplateType(ModularComponentTemplateType):
     _name: str
@@ -446,7 +463,8 @@ class InterfaceTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.InventoryItem,
     exclude=['component_type', 'component_id', 'parent'],
-    filters=InventoryItemFilter
+    filters=InventoryItemFilter,
+    pagination=True
 )
 class InventoryItemType(ComponentType):
     role: Annotated["InventoryItemRoleType", strawberry.lazy('dcim.graphql.types')] | None
@@ -472,7 +490,8 @@ class InventoryItemType(ComponentType):
 @strawberry_django.type(
     models.InventoryItemRole,
     fields='__all__',
-    filters=InventoryItemRoleFilter
+    filters=InventoryItemRoleFilter,
+    pagination=True
 )
 class InventoryItemRoleType(OrganizationalObjectType):
     color: str
@@ -485,7 +504,8 @@ class InventoryItemRoleType(OrganizationalObjectType):
     models.Location,
     # fields='__all__',
     exclude=['parent'],  # bug - temp
-    filters=LocationFilter
+    filters=LocationFilter,
+    pagination=True
 )
 class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, OrganizationalObjectType):
     site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
@@ -512,7 +532,8 @@ class LocationType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, Organi
 @strawberry_django.type(
     models.Manufacturer,
     fields='__all__',
-    filters=ManufacturerFilter
+    filters=ManufacturerFilter,
+    pagination=True
 )
 class ManufacturerType(OrganizationalObjectType, ContactsMixin):
 
@@ -526,7 +547,8 @@ class ManufacturerType(OrganizationalObjectType, ContactsMixin):
 @strawberry_django.type(
     models.Module,
     fields='__all__',
-    filters=ModuleFilter
+    filters=ModuleFilter,
+    pagination=True
 )
 class ModuleType(NetBoxObjectType):
     device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')]
@@ -546,7 +568,8 @@ class ModuleType(NetBoxObjectType):
     models.ModuleBay,
     # fields='__all__',
     exclude=['parent'],
-    filters=ModuleBayFilter
+    filters=ModuleBayFilter,
+    pagination=True
 )
 class ModuleBayType(ModularComponentType):
 
@@ -561,7 +584,8 @@ class ModuleBayType(ModularComponentType):
 @strawberry_django.type(
     models.ModuleBayTemplate,
     fields='__all__',
-    filters=ModuleBayTemplateFilter
+    filters=ModuleBayTemplateFilter,
+    pagination=True
 )
 class ModuleBayTemplateType(ModularComponentTemplateType):
     pass
@@ -570,7 +594,8 @@ class ModuleBayTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.ModuleType,
     fields='__all__',
-    filters=ModuleTypeFilter
+    filters=ModuleTypeFilter,
+    pagination=True
 )
 class ModuleTypeType(NetBoxObjectType):
     manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')]
@@ -588,7 +613,8 @@ class ModuleTypeType(NetBoxObjectType):
 @strawberry_django.type(
     models.Platform,
     fields='__all__',
-    filters=PlatformFilter
+    filters=PlatformFilter,
+    pagination=True
 )
 class PlatformType(OrganizationalObjectType):
     manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')] | None
@@ -601,7 +627,8 @@ class PlatformType(OrganizationalObjectType):
 @strawberry_django.type(
     models.PowerFeed,
     exclude=['_path'],
-    filters=PowerFeedFilter
+    filters=PowerFeedFilter,
+    pagination=True
 )
 class PowerFeedType(NetBoxObjectType, CabledObjectMixin, PathEndpointMixin):
     power_panel: Annotated["PowerPanelType", strawberry.lazy('dcim.graphql.types')]
@@ -612,7 +639,8 @@ class PowerFeedType(NetBoxObjectType, CabledObjectMixin, PathEndpointMixin):
 @strawberry_django.type(
     models.PowerOutlet,
     exclude=['_path'],
-    filters=PowerOutletFilter
+    filters=PowerOutletFilter,
+    pagination=True
 )
 class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
     power_port: Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')] | None
@@ -622,7 +650,8 @@ class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin
 @strawberry_django.type(
     models.PowerOutletTemplate,
     fields='__all__',
-    filters=PowerOutletTemplateFilter
+    filters=PowerOutletTemplateFilter,
+    pagination=True
 )
 class PowerOutletTemplateType(ModularComponentTemplateType):
     power_port: Annotated["PowerPortTemplateType", strawberry.lazy('dcim.graphql.types')] | None
@@ -631,7 +660,8 @@ class PowerOutletTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.PowerPanel,
     fields='__all__',
-    filters=PowerPanelFilter
+    filters=PowerPanelFilter,
+    pagination=True
 )
 class PowerPanelType(NetBoxObjectType, ContactsMixin):
     site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
@@ -643,7 +673,8 @@ class PowerPanelType(NetBoxObjectType, ContactsMixin):
 @strawberry_django.type(
     models.PowerPort,
     exclude=['_path'],
-    filters=PowerPortFilter
+    filters=PowerPortFilter,
+    pagination=True
 )
 class PowerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
 
@@ -653,7 +684,8 @@ class PowerPortType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
 @strawberry_django.type(
     models.PowerPortTemplate,
     fields='__all__',
-    filters=PowerPortTemplateFilter
+    filters=PowerPortTemplateFilter,
+    pagination=True
 )
 class PowerPortTemplateType(ModularComponentTemplateType):
     poweroutlet_templates: List[Annotated["PowerOutletTemplateType", strawberry.lazy('dcim.graphql.types')]]
@@ -662,7 +694,8 @@ class PowerPortTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.RackType,
     fields='__all__',
-    filters=RackTypeFilter
+    filters=RackTypeFilter,
+    pagination=True
 )
 class RackTypeType(NetBoxObjectType):
     manufacturer: Annotated["ManufacturerType", strawberry.lazy('dcim.graphql.types')]
@@ -671,7 +704,8 @@ class RackTypeType(NetBoxObjectType):
 @strawberry_django.type(
     models.Rack,
     fields='__all__',
-    filters=RackFilter
+    filters=RackFilter,
+    pagination=True
 )
 class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
     site: Annotated["SiteType", strawberry.lazy('dcim.graphql.types')]
@@ -689,7 +723,8 @@ class RackType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObje
 @strawberry_django.type(
     models.RackReservation,
     fields='__all__',
-    filters=RackReservationFilter
+    filters=RackReservationFilter,
+    pagination=True
 )
 class RackReservationType(NetBoxObjectType):
     units: List[int]
@@ -701,7 +736,8 @@ class RackReservationType(NetBoxObjectType):
 @strawberry_django.type(
     models.RackRole,
     fields='__all__',
-    filters=RackRoleFilter
+    filters=RackRoleFilter,
+    pagination=True
 )
 class RackRoleType(OrganizationalObjectType):
     color: str
@@ -712,7 +748,8 @@ class RackRoleType(OrganizationalObjectType):
 @strawberry_django.type(
     models.RearPort,
     fields='__all__',
-    filters=RearPortFilter
+    filters=RearPortFilter,
+    pagination=True
 )
 class RearPortType(ModularComponentType, CabledObjectMixin):
     color: str
@@ -723,7 +760,8 @@ class RearPortType(ModularComponentType, CabledObjectMixin):
 @strawberry_django.type(
     models.RearPortTemplate,
     fields='__all__',
-    filters=RearPortTemplateFilter
+    filters=RearPortTemplateFilter,
+    pagination=True
 )
 class RearPortTemplateType(ModularComponentTemplateType):
     color: str
@@ -734,7 +772,8 @@ class RearPortTemplateType(ModularComponentTemplateType):
 @strawberry_django.type(
     models.Region,
     exclude=['parent'],
-    filters=RegionFilter
+    filters=RegionFilter,
+    pagination=True
 )
 class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
 
@@ -759,7 +798,8 @@ class RegionType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
 @strawberry_django.type(
     models.Site,
     fields='__all__',
-    filters=SiteFilter
+    filters=SiteFilter,
+    pagination=True
 )
 class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObjectType):
     time_zone: str | None
@@ -793,7 +833,8 @@ class SiteType(VLANGroupsMixin, ImageAttachmentsMixin, ContactsMixin, NetBoxObje
 @strawberry_django.type(
     models.SiteGroup,
     exclude=['parent'],  # bug - temp
-    filters=SiteGroupFilter
+    filters=SiteGroupFilter,
+    pagination=True
 )
 class SiteGroupType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
 
@@ -818,7 +859,8 @@ class SiteGroupType(VLANGroupsMixin, ContactsMixin, OrganizationalObjectType):
 @strawberry_django.type(
     models.VirtualChassis,
     fields='__all__',
-    filters=VirtualChassisFilter
+    filters=VirtualChassisFilter,
+    pagination=True
 )
 class VirtualChassisType(NetBoxObjectType):
     member_count: BigInt
@@ -830,7 +872,8 @@ class VirtualChassisType(NetBoxObjectType):
 @strawberry_django.type(
     models.VirtualDeviceContext,
     fields='__all__',
-    filters=VirtualDeviceContextFilter
+    filters=VirtualDeviceContextFilter,
+    pagination=True
 )
 class VirtualDeviceContextType(NetBoxObjectType):
     device: Annotated["DeviceType", strawberry.lazy('dcim.graphql.types')] | None

+ 28 - 13
netbox/extras/graphql/types.py

@@ -46,7 +46,8 @@ __all__ = (
 @strawberry_django.type(
     models.ConfigContext,
     fields='__all__',
-    filters=ConfigContextFilter
+    filters=ConfigContextFilter,
+    pagination=True
 )
 class ConfigContextType(ObjectType):
     data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
@@ -69,7 +70,8 @@ class ConfigContextType(ObjectType):
 @strawberry_django.type(
     models.ConfigTemplate,
     fields='__all__',
-    filters=ConfigTemplateFilter
+    filters=ConfigTemplateFilter,
+    pagination=True
 )
 class ConfigTemplateType(TagsMixin, ObjectType):
     data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
@@ -84,7 +86,8 @@ class ConfigTemplateType(TagsMixin, ObjectType):
 @strawberry_django.type(
     models.CustomField,
     fields='__all__',
-    filters=CustomFieldFilter
+    filters=CustomFieldFilter,
+    pagination=True
 )
 class CustomFieldType(ObjectType):
     related_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
@@ -94,7 +97,8 @@ class CustomFieldType(ObjectType):
 @strawberry_django.type(
     models.CustomFieldChoiceSet,
     exclude=['extra_choices'],
-    filters=CustomFieldChoiceSetFilter
+    filters=CustomFieldChoiceSetFilter,
+    pagination=True
 )
 class CustomFieldChoiceSetType(ObjectType):
 
@@ -105,7 +109,8 @@ class CustomFieldChoiceSetType(ObjectType):
 @strawberry_django.type(
     models.CustomLink,
     fields='__all__',
-    filters=CustomLinkFilter
+    filters=CustomLinkFilter,
+    pagination=True
 )
 class CustomLinkType(ObjectType):
     pass
@@ -114,7 +119,8 @@ class CustomLinkType(ObjectType):
 @strawberry_django.type(
     models.ExportTemplate,
     fields='__all__',
-    filters=ExportTemplateFilter
+    filters=ExportTemplateFilter,
+    pagination=True
 )
 class ExportTemplateType(ObjectType):
     data_source: Annotated["DataSourceType", strawberry.lazy('core.graphql.types')] | None
@@ -124,7 +130,8 @@ class ExportTemplateType(ObjectType):
 @strawberry_django.type(
     models.ImageAttachment,
     fields='__all__',
-    filters=ImageAttachmentFilter
+    filters=ImageAttachmentFilter,
+    pagination=True
 )
 class ImageAttachmentType(BaseObjectType):
     object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
@@ -133,7 +140,8 @@ class ImageAttachmentType(BaseObjectType):
 @strawberry_django.type(
     models.JournalEntry,
     fields='__all__',
-    filters=JournalEntryFilter
+    filters=JournalEntryFilter,
+    pagination=True
 )
 class JournalEntryType(CustomFieldsMixin, TagsMixin, ObjectType):
     assigned_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None
@@ -143,6 +151,7 @@ class JournalEntryType(CustomFieldsMixin, TagsMixin, ObjectType):
 @strawberry_django.type(
     models.Notification,
     # filters=NotificationFilter
+    pagination=True
 )
 class NotificationType(ObjectType):
     user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
@@ -150,7 +159,8 @@ class NotificationType(ObjectType):
 
 @strawberry_django.type(
     models.NotificationGroup,
-    filters=NotificationGroupFilter
+    filters=NotificationGroupFilter,
+    pagination=True
 )
 class NotificationGroupType(ObjectType):
     users: List[Annotated["UserType", strawberry.lazy('users.graphql.types')]]
@@ -160,7 +170,8 @@ class NotificationGroupType(ObjectType):
 @strawberry_django.type(
     models.SavedFilter,
     exclude=['content_types',],
-    filters=SavedFilterFilter
+    filters=SavedFilterFilter,
+    pagination=True
 )
 class SavedFilterType(ObjectType):
     user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
@@ -169,6 +180,7 @@ class SavedFilterType(ObjectType):
 @strawberry_django.type(
     models.Subscription,
     # filters=NotificationFilter
+    pagination=True
 )
 class SubscriptionType(ObjectType):
     user: Annotated["UserType", strawberry.lazy('users.graphql.types')] | None
@@ -177,7 +189,8 @@ class SubscriptionType(ObjectType):
 @strawberry_django.type(
     models.Tag,
     exclude=['extras_taggeditem_items', ],
-    filters=TagFilter
+    filters=TagFilter,
+    pagination=True
 )
 class TagType(ObjectType):
     color: str
@@ -188,7 +201,8 @@ class TagType(ObjectType):
 @strawberry_django.type(
     models.Webhook,
     exclude=['content_types',],
-    filters=WebhookFilter
+    filters=WebhookFilter,
+    pagination=True
 )
 class WebhookType(OrganizationalObjectType):
     pass
@@ -197,7 +211,8 @@ class WebhookType(OrganizationalObjectType):
 @strawberry_django.type(
     models.EventRule,
     exclude=['content_types',],
-    filters=EventRuleFilter
+    filters=EventRuleFilter,
+    pagination=True
 )
 class EventRuleType(OrganizationalObjectType):
     action_object_type: Annotated["ContentTypeType", strawberry.lazy('netbox.graphql.types')] | None

+ 36 - 18
netbox/ipam/graphql/types.py

@@ -70,7 +70,8 @@ class BaseIPAddressFamilyType:
 @strawberry_django.type(
     models.ASN,
     fields='__all__',
-    filters=ASNFilter
+    filters=ASNFilter,
+    pagination=True
 )
 class ASNType(NetBoxObjectType):
     asn: BigInt
@@ -84,7 +85,8 @@ class ASNType(NetBoxObjectType):
 @strawberry_django.type(
     models.ASNRange,
     fields='__all__',
-    filters=ASNRangeFilter
+    filters=ASNRangeFilter,
+    pagination=True
 )
 class ASNRangeType(NetBoxObjectType):
     start: BigInt
@@ -96,7 +98,8 @@ class ASNRangeType(NetBoxObjectType):
 @strawberry_django.type(
     models.Aggregate,
     fields='__all__',
-    filters=AggregateFilter
+    filters=AggregateFilter,
+    pagination=True
 )
 class AggregateType(NetBoxObjectType, BaseIPAddressFamilyType):
     prefix: str
@@ -107,7 +110,8 @@ class AggregateType(NetBoxObjectType, BaseIPAddressFamilyType):
 @strawberry_django.type(
     models.FHRPGroup,
     fields='__all__',
-    filters=FHRPGroupFilter
+    filters=FHRPGroupFilter,
+    pagination=True
 )
 class FHRPGroupType(NetBoxObjectType, IPAddressesMixin):
 
@@ -117,7 +121,8 @@ class FHRPGroupType(NetBoxObjectType, IPAddressesMixin):
 @strawberry_django.type(
     models.FHRPGroupAssignment,
     exclude=['interface_type', 'interface_id'],
-    filters=FHRPGroupAssignmentFilter
+    filters=FHRPGroupAssignmentFilter,
+    pagination=True
 )
 class FHRPGroupAssignmentType(BaseObjectType):
     group: Annotated["FHRPGroupType", strawberry.lazy('ipam.graphql.types')]
@@ -133,7 +138,8 @@ class FHRPGroupAssignmentType(BaseObjectType):
 @strawberry_django.type(
     models.IPAddress,
     exclude=['assigned_object_type', 'assigned_object_id', 'address'],
-    filters=IPAddressFilter
+    filters=IPAddressFilter,
+    pagination=True
 )
 class IPAddressType(NetBoxObjectType, BaseIPAddressFamilyType):
     address: str
@@ -157,7 +163,8 @@ class IPAddressType(NetBoxObjectType, BaseIPAddressFamilyType):
 @strawberry_django.type(
     models.IPRange,
     fields='__all__',
-    filters=IPRangeFilter
+    filters=IPRangeFilter,
+    pagination=True
 )
 class IPRangeType(NetBoxObjectType):
     start_address: str
@@ -170,7 +177,8 @@ class IPRangeType(NetBoxObjectType):
 @strawberry_django.type(
     models.Prefix,
     exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'],
-    filters=PrefixFilter
+    filters=PrefixFilter,
+    pagination=True
 )
 class PrefixType(NetBoxObjectType, BaseIPAddressFamilyType):
     prefix: str
@@ -192,7 +200,8 @@ class PrefixType(NetBoxObjectType, BaseIPAddressFamilyType):
 @strawberry_django.type(
     models.RIR,
     fields='__all__',
-    filters=RIRFilter
+    filters=RIRFilter,
+    pagination=True
 )
 class RIRType(OrganizationalObjectType):
 
@@ -204,7 +213,8 @@ class RIRType(OrganizationalObjectType):
 @strawberry_django.type(
     models.Role,
     fields='__all__',
-    filters=RoleFilter
+    filters=RoleFilter,
+    pagination=True
 )
 class RoleType(OrganizationalObjectType):
 
@@ -216,7 +226,8 @@ class RoleType(OrganizationalObjectType):
 @strawberry_django.type(
     models.RouteTarget,
     fields='__all__',
-    filters=RouteTargetFilter
+    filters=RouteTargetFilter,
+    pagination=True
 )
 class RouteTargetType(NetBoxObjectType):
     tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
@@ -230,7 +241,8 @@ class RouteTargetType(NetBoxObjectType):
 @strawberry_django.type(
     models.Service,
     fields='__all__',
-    filters=ServiceFilter
+    filters=ServiceFilter,
+    pagination=True
 )
 class ServiceType(NetBoxObjectType):
     ports: List[int]
@@ -243,7 +255,8 @@ class ServiceType(NetBoxObjectType):
 @strawberry_django.type(
     models.ServiceTemplate,
     fields='__all__',
-    filters=ServiceTemplateFilter
+    filters=ServiceTemplateFilter,
+    pagination=True
 )
 class ServiceTemplateType(NetBoxObjectType):
     ports: List[int]
@@ -252,7 +265,8 @@ class ServiceTemplateType(NetBoxObjectType):
 @strawberry_django.type(
     models.VLAN,
     exclude=['qinq_svlan'],
-    filters=VLANFilter
+    filters=VLANFilter,
+    pagination=True
 )
 class VLANType(NetBoxObjectType):
     site: Annotated["SiteType", strawberry.lazy('ipam.graphql.types')] | None
@@ -275,7 +289,8 @@ class VLANType(NetBoxObjectType):
 @strawberry_django.type(
     models.VLANGroup,
     exclude=['scope_type', 'scope_id'],
-    filters=VLANGroupFilter
+    filters=VLANGroupFilter,
+    pagination=True
 )
 class VLANGroupType(OrganizationalObjectType):
 
@@ -299,7 +314,8 @@ class VLANGroupType(OrganizationalObjectType):
 @strawberry_django.type(
     models.VLANTranslationPolicy,
     fields='__all__',
-    filters=VLANTranslationPolicyFilter
+    filters=VLANTranslationPolicyFilter,
+    pagination=True
 )
 class VLANTranslationPolicyType(NetBoxObjectType):
     rules: List[Annotated["VLANTranslationRuleType", strawberry.lazy('ipam.graphql.types')]]
@@ -308,7 +324,8 @@ class VLANTranslationPolicyType(NetBoxObjectType):
 @strawberry_django.type(
     models.VLANTranslationRule,
     fields='__all__',
-    filters=VLANTranslationRuleFilter
+    filters=VLANTranslationRuleFilter,
+    pagination=True
 )
 class VLANTranslationRuleType(NetBoxObjectType):
     policy: Annotated[
@@ -320,7 +337,8 @@ class VLANTranslationRuleType(NetBoxObjectType):
 @strawberry_django.type(
     models.VRF,
     fields='__all__',
-    filters=VRFFilter
+    filters=VRFFilter,
+    pagination=True
 )
 class VRFType(NetBoxObjectType):
     tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None

+ 1 - 1
netbox/netbox/graphql/schema.py

@@ -1,7 +1,7 @@
 import strawberry
 from django.conf import settings
 from strawberry_django.optimizer import DjangoOptimizerExtension
-from strawberry.extensions import MaxAliasesLimiter
+from strawberry.extensions import MaxAliasesLimiter  # , SchemaExtension
 from strawberry.schema.config import StrawberryConfig
 
 from circuits.graphql.schema import CircuitsQuery

+ 2 - 0
netbox/netbox/graphql/types.py

@@ -84,6 +84,7 @@ class NetBoxObjectType(
 @strawberry_django.type(
     ContentType,
     fields=['id', 'app_label', 'model'],
+    pagination=True
 )
 class ContentTypeType:
     pass
@@ -92,6 +93,7 @@ class ContentTypeType:
 @strawberry_django.type(
     ObjectType_,
     fields=['id', 'app_label', 'model'],
+    pagination=True
 )
 class ObjectTypeType:
     pass

+ 1 - 0
netbox/netbox/settings.py

@@ -798,6 +798,7 @@ LOCALE_PATHS = (
 STRAWBERRY_DJANGO = {
     "DEFAULT_PK_FIELD_NAME": "id",
     "TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True,
+    "PAGINATION_DEFAULT_LIMIT": 100,
 }
 
 #

+ 36 - 6
netbox/tenancy/graphql/types.py

@@ -52,7 +52,12 @@ __all__ = (
 #
 
 
-@strawberry_django.type(models.Tenant, fields='__all__', filters=TenantFilter)
+@strawberry_django.type(
+    models.Tenant,
+    fields='__all__',
+    filters=TenantFilter,
+    pagination=True
+)
 class TenantType(NetBoxObjectType):
     group: Annotated['TenantGroupType', strawberry.lazy('tenancy.graphql.types')] | None
     contacts: List[Annotated['ContactType', strawberry.lazy('tenancy.graphql.types')]]
@@ -82,7 +87,12 @@ class TenantType(NetBoxObjectType):
     l2vpns: List[Annotated['L2VPNType', strawberry.lazy('vpn.graphql.types')]]
 
 
-@strawberry_django.type(models.TenantGroup, fields='__all__', filters=TenantGroupFilter)
+@strawberry_django.type(
+    models.TenantGroup,
+    fields='__all__',
+    filters=TenantGroupFilter,
+    pagination=True
+)
 class TenantGroupType(OrganizationalObjectType):
     parent: Annotated['TenantGroupType', strawberry.lazy('tenancy.graphql.types')] | None
 
@@ -95,17 +105,32 @@ class TenantGroupType(OrganizationalObjectType):
 #
 
 
-@strawberry_django.type(models.Contact, fields='__all__', filters=ContactFilter)
+@strawberry_django.type(
+    models.Contact,
+    fields='__all__',
+    filters=ContactFilter,
+    pagination=True
+)
 class ContactType(ContactAssignmentsMixin, NetBoxObjectType):
     groups: List[Annotated['ContactGroupType', strawberry.lazy('tenancy.graphql.types')]]
 
 
-@strawberry_django.type(models.ContactRole, fields='__all__', filters=ContactRoleFilter)
+@strawberry_django.type(
+    models.ContactRole,
+    fields='__all__',
+    filters=ContactRoleFilter,
+    pagination=True
+)
 class ContactRoleType(ContactAssignmentsMixin, OrganizationalObjectType):
     pass
 
 
-@strawberry_django.type(models.ContactGroup, fields='__all__', filters=ContactGroupFilter)
+@strawberry_django.type(
+    models.ContactGroup,
+    fields='__all__',
+    filters=ContactGroupFilter,
+    pagination=True
+)
 class ContactGroupType(OrganizationalObjectType):
     parent: Annotated['ContactGroupType', strawberry.lazy('tenancy.graphql.types')] | None
 
@@ -113,7 +138,12 @@ class ContactGroupType(OrganizationalObjectType):
     children: List[Annotated['ContactGroupType', strawberry.lazy('tenancy.graphql.types')]]
 
 
-@strawberry_django.type(models.ContactAssignment, fields='__all__', filters=ContactAssignmentFilter)
+@strawberry_django.type(
+    models.ContactAssignment,
+    fields='__all__',
+    filters=ContactAssignmentFilter,
+    pagination=True
+)
 class ContactAssignmentType(CustomFieldsMixin, TagsMixin, BaseObjectType):
     object_type: Annotated['ContentTypeType', strawberry.lazy('netbox.graphql.types')] | None
     contact: Annotated['ContactType', strawberry.lazy('tenancy.graphql.types')] | None

+ 4 - 2
netbox/users/graphql/types.py

@@ -15,7 +15,8 @@ __all__ = (
 @strawberry_django.type(
     Group,
     fields=['id', 'name'],
-    filters=GroupFilter
+    filters=GroupFilter,
+    pagination=True
 )
 class GroupType(BaseObjectType):
     pass
@@ -26,7 +27,8 @@ class GroupType(BaseObjectType):
     fields=[
         'id', 'username', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'date_joined', 'groups',
     ],
-    filters=UserFilter
+    filters=UserFilter,
+    pagination=True
 )
 class UserType(BaseObjectType):
     groups: List[GroupType]

+ 12 - 6
netbox/virtualization/graphql/types.py

@@ -46,7 +46,8 @@ class ComponentType(NetBoxObjectType):
 @strawberry_django.type(
     models.Cluster,
     exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'],
-    filters=ClusterFilter
+    filters=ClusterFilter,
+    pagination=True
 )
 class ClusterType(VLANGroupsMixin, NetBoxObjectType):
     type: Annotated["ClusterTypeType", strawberry.lazy('virtualization.graphql.types')] | None
@@ -68,7 +69,8 @@ class ClusterType(VLANGroupsMixin, NetBoxObjectType):
 @strawberry_django.type(
     models.ClusterGroup,
     fields='__all__',
-    filters=ClusterGroupFilter
+    filters=ClusterGroupFilter,
+    pagination=True
 )
 class ClusterGroupType(VLANGroupsMixin, OrganizationalObjectType):
 
@@ -78,7 +80,8 @@ class ClusterGroupType(VLANGroupsMixin, OrganizationalObjectType):
 @strawberry_django.type(
     models.ClusterType,
     fields='__all__',
-    filters=ClusterTypeFilter
+    filters=ClusterTypeFilter,
+    pagination=True
 )
 class ClusterTypeType(OrganizationalObjectType):
 
@@ -88,7 +91,8 @@ class ClusterTypeType(OrganizationalObjectType):
 @strawberry_django.type(
     models.VirtualMachine,
     fields='__all__',
-    filters=VirtualMachineFilter
+    filters=VirtualMachineFilter,
+    pagination=True
 )
 class VirtualMachineType(ConfigContextMixin, ContactsMixin, NetBoxObjectType):
     interface_count: BigInt
@@ -112,7 +116,8 @@ class VirtualMachineType(ConfigContextMixin, ContactsMixin, NetBoxObjectType):
 @strawberry_django.type(
     models.VMInterface,
     fields='__all__',
-    filters=VMInterfaceFilter
+    filters=VMInterfaceFilter,
+    pagination=True
 )
 class VMInterfaceType(IPAddressesMixin, ComponentType):
     _name: str
@@ -134,7 +139,8 @@ class VMInterfaceType(IPAddressesMixin, ComponentType):
 @strawberry_django.type(
     models.VirtualDisk,
     fields='__all__',
-    filters=VirtualDiskFilter
+    filters=VirtualDiskFilter,
+    pagination=True
 )
 class VirtualDiskType(ComponentType):
     pass

+ 20 - 10
netbox/vpn/graphql/types.py

@@ -32,7 +32,8 @@ __all__ = (
 @strawberry_django.type(
     models.TunnelGroup,
     fields='__all__',
-    filters=TunnelGroupFilter
+    filters=TunnelGroupFilter,
+    pagination=True
 )
 class TunnelGroupType(OrganizationalObjectType):
 
@@ -42,7 +43,8 @@ class TunnelGroupType(OrganizationalObjectType):
 @strawberry_django.type(
     models.TunnelTermination,
     fields='__all__',
-    filters=TunnelTerminationFilter
+    filters=TunnelTerminationFilter,
+    pagination=True
 )
 class TunnelTerminationType(CustomFieldsMixin, TagsMixin, ObjectType):
     tunnel: Annotated["TunnelType", strawberry.lazy('vpn.graphql.types')]
@@ -53,7 +55,8 @@ class TunnelTerminationType(CustomFieldsMixin, TagsMixin, ObjectType):
 @strawberry_django.type(
     models.Tunnel,
     fields='__all__',
-    filters=TunnelFilter
+    filters=TunnelFilter,
+    pagination=True
 )
 class TunnelType(NetBoxObjectType):
     group: Annotated["TunnelGroupType", strawberry.lazy('vpn.graphql.types')] | None
@@ -66,7 +69,8 @@ class TunnelType(NetBoxObjectType):
 @strawberry_django.type(
     models.IKEProposal,
     fields='__all__',
-    filters=IKEProposalFilter
+    filters=IKEProposalFilter,
+    pagination=True
 )
 class IKEProposalType(OrganizationalObjectType):
 
@@ -76,7 +80,8 @@ class IKEProposalType(OrganizationalObjectType):
 @strawberry_django.type(
     models.IKEPolicy,
     fields='__all__',
-    filters=IKEPolicyFilter
+    filters=IKEPolicyFilter,
+    pagination=True
 )
 class IKEPolicyType(OrganizationalObjectType):
 
@@ -87,7 +92,8 @@ class IKEPolicyType(OrganizationalObjectType):
 @strawberry_django.type(
     models.IPSecProposal,
     fields='__all__',
-    filters=IPSecProposalFilter
+    filters=IPSecProposalFilter,
+    pagination=True
 )
 class IPSecProposalType(OrganizationalObjectType):
 
@@ -97,7 +103,8 @@ class IPSecProposalType(OrganizationalObjectType):
 @strawberry_django.type(
     models.IPSecPolicy,
     fields='__all__',
-    filters=IPSecPolicyFilter
+    filters=IPSecPolicyFilter,
+    pagination=True
 )
 class IPSecPolicyType(OrganizationalObjectType):
 
@@ -108,7 +115,8 @@ class IPSecPolicyType(OrganizationalObjectType):
 @strawberry_django.type(
     models.IPSecProfile,
     fields='__all__',
-    filters=IPSecProfileFilter
+    filters=IPSecProfileFilter,
+    pagination=True
 )
 class IPSecProfileType(OrganizationalObjectType):
     ike_policy: Annotated["IKEPolicyType", strawberry.lazy('vpn.graphql.types')]
@@ -120,7 +128,8 @@ class IPSecProfileType(OrganizationalObjectType):
 @strawberry_django.type(
     models.L2VPN,
     fields='__all__',
-    filters=L2VPNFilter
+    filters=L2VPNFilter,
+    pagination=True
 )
 class L2VPNType(ContactsMixin, NetBoxObjectType):
     tenant: Annotated["TenantType", strawberry.lazy('tenancy.graphql.types')] | None
@@ -133,7 +142,8 @@ class L2VPNType(ContactsMixin, NetBoxObjectType):
 @strawberry_django.type(
     models.L2VPNTermination,
     exclude=['assigned_object_type', 'assigned_object_id'],
-    filters=L2VPNTerminationFilter
+    filters=L2VPNTerminationFilter,
+    pagination=True
 )
 class L2VPNTerminationType(NetBoxObjectType):
     l2vpn: Annotated["L2VPNType", strawberry.lazy('vpn.graphql.types')]

+ 6 - 3
netbox/wireless/graphql/types.py

@@ -22,7 +22,8 @@ __all__ = (
 @strawberry_django.type(
     models.WirelessLANGroup,
     fields='__all__',
-    filters=WirelessLANGroupFilter
+    filters=WirelessLANGroupFilter,
+    pagination=True
 )
 class WirelessLANGroupType(OrganizationalObjectType):
     parent: Annotated["WirelessLANGroupType", strawberry.lazy('wireless.graphql.types')] | None
@@ -34,7 +35,8 @@ class WirelessLANGroupType(OrganizationalObjectType):
 @strawberry_django.type(
     models.WirelessLAN,
     exclude=['scope_type', 'scope_id', '_location', '_region', '_site', '_site_group'],
-    filters=WirelessLANFilter
+    filters=WirelessLANFilter,
+    pagination=True
 )
 class WirelessLANType(NetBoxObjectType):
     group: Annotated["WirelessLANGroupType", strawberry.lazy('wireless.graphql.types')] | None
@@ -56,7 +58,8 @@ class WirelessLANType(NetBoxObjectType):
 @strawberry_django.type(
     models.WirelessLink,
     fields='__all__',
-    filters=WirelessLinkFilter
+    filters=WirelessLinkFilter,
+    pagination=True
 )
 class WirelessLinkType(NetBoxObjectType):
     interface_a: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]