mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
Use _list appendix for GraphQL list queries
This commit is contained in:
parent
0d7309cb19
commit
728b3bac67
@ -42,8 +42,10 @@ The response will include the requested data formatted as JSON:
|
|||||||
|
|
||||||
NetBox provides both a singular and plural query field for each object type:
|
NetBox provides both a singular and plural query field for each object type:
|
||||||
|
|
||||||
* `object`: Returns a single object. Must specify the object's unique ID as `(id: 123)`.
|
* `$OBJECT`: Returns a single object. Must specify the object's unique ID as `(id: 123)`.
|
||||||
* `objects`: Returns a list of objects, optionally filtered by given parameters.
|
* `$OBJECT_list`: Returns a list of objects, optionally filtered by given parameters.
|
||||||
|
|
||||||
|
For example, query `device(id:123)` to fetch a specific device (identified by its unique ID), and query `device_list` (with an optional set of fitlers) to fetch all devices.
|
||||||
|
|
||||||
For more detail on constructing GraphQL queries, see the [Graphene documentation](https://docs.graphene-python.org/en/latest/).
|
For more detail on constructing GraphQL queries, see the [Graphene documentation](https://docs.graphene-python.org/en/latest/).
|
||||||
|
|
||||||
|
@ -6,16 +6,16 @@ from .types import *
|
|||||||
|
|
||||||
class CircuitsQuery(graphene.ObjectType):
|
class CircuitsQuery(graphene.ObjectType):
|
||||||
circuit = ObjectField(CircuitType)
|
circuit = ObjectField(CircuitType)
|
||||||
circuits = ObjectListField(CircuitType)
|
circuit_list = ObjectListField(CircuitType)
|
||||||
|
|
||||||
circuit_termination = ObjectField(CircuitTerminationType)
|
circuit_termination = ObjectField(CircuitTerminationType)
|
||||||
circuit_terminations = ObjectListField(CircuitTerminationType)
|
circuit_termination_list = ObjectListField(CircuitTerminationType)
|
||||||
|
|
||||||
circuit_type = ObjectField(CircuitTypeType)
|
circuit_type = ObjectField(CircuitTypeType)
|
||||||
circuit_types = ObjectListField(CircuitTypeType)
|
circuit_type_list = ObjectListField(CircuitTypeType)
|
||||||
|
|
||||||
provider = ObjectField(ProviderType)
|
provider = ObjectField(ProviderType)
|
||||||
providers = ObjectListField(ProviderType)
|
provider_list = ObjectListField(ProviderType)
|
||||||
|
|
||||||
provider_network = ObjectField(ProviderNetworkType)
|
provider_network = ObjectField(ProviderNetworkType)
|
||||||
provider_networks = ObjectListField(ProviderNetworkType)
|
provider_network_list = ObjectListField(ProviderNetworkType)
|
||||||
|
@ -6,101 +6,100 @@ from .types import *
|
|||||||
|
|
||||||
class DCIMQuery(graphene.ObjectType):
|
class DCIMQuery(graphene.ObjectType):
|
||||||
cable = ObjectField(CableType)
|
cable = ObjectField(CableType)
|
||||||
cables = ObjectListField(CableType)
|
cable_list = ObjectListField(CableType)
|
||||||
|
|
||||||
console_port = ObjectField(ConsolePortType)
|
console_port = ObjectField(ConsolePortType)
|
||||||
console_ports = ObjectListField(ConsolePortType)
|
console_port_list = ObjectListField(ConsolePortType)
|
||||||
|
|
||||||
console_port_template = ObjectField(ConsolePortTemplateType)
|
console_port_template = ObjectField(ConsolePortTemplateType)
|
||||||
console_port_templates = ObjectListField(ConsolePortTemplateType)
|
console_port_template_list = ObjectListField(ConsolePortTemplateType)
|
||||||
|
|
||||||
console_server_port = ObjectField(ConsoleServerPortType)
|
console_server_port = ObjectField(ConsoleServerPortType)
|
||||||
console_server_ports = ObjectListField(ConsoleServerPortType)
|
console_server_port_list = ObjectListField(ConsoleServerPortType)
|
||||||
|
|
||||||
console_server_port_template = ObjectField(ConsoleServerPortTemplateType)
|
console_server_port_template = ObjectField(ConsoleServerPortTemplateType)
|
||||||
console_server_port_templates = ObjectListField(ConsoleServerPortTemplateType)
|
console_server_port_template_list = ObjectListField(ConsoleServerPortTemplateType)
|
||||||
|
|
||||||
device = ObjectField(DeviceType)
|
device = ObjectField(DeviceType)
|
||||||
devices = ObjectListField(DeviceType)
|
device_list = ObjectListField(DeviceType)
|
||||||
|
|
||||||
device_bay = ObjectField(DeviceBayType)
|
device_bay = ObjectField(DeviceBayType)
|
||||||
device_bays = ObjectListField(DeviceBayType)
|
device_bay_list = ObjectListField(DeviceBayType)
|
||||||
|
|
||||||
device_bay_template = ObjectField(DeviceBayTemplateType)
|
device_bay_template = ObjectField(DeviceBayTemplateType)
|
||||||
device_bay_templates = ObjectListField(DeviceBayTemplateType)
|
device_bay_template_list = ObjectListField(DeviceBayTemplateType)
|
||||||
|
|
||||||
device_role = ObjectField(DeviceRoleType)
|
device_role = ObjectField(DeviceRoleType)
|
||||||
device_roles = ObjectListField(DeviceRoleType)
|
device_role_list = ObjectListField(DeviceRoleType)
|
||||||
|
|
||||||
device_type = ObjectField(DeviceTypeType)
|
device_type = ObjectField(DeviceTypeType)
|
||||||
device_types = ObjectListField(DeviceTypeType)
|
device_type_list = ObjectListField(DeviceTypeType)
|
||||||
|
|
||||||
front_port = ObjectField(FrontPortType)
|
front_port = ObjectField(FrontPortType)
|
||||||
front_ports = ObjectListField(FrontPortType)
|
front_port_list = ObjectListField(FrontPortType)
|
||||||
|
|
||||||
front_port_template = ObjectField(FrontPortTemplateType)
|
front_port_template = ObjectField(FrontPortTemplateType)
|
||||||
front_port_templates = ObjectListField(FrontPortTemplateType)
|
front_port_template_list = ObjectListField(FrontPortTemplateType)
|
||||||
|
|
||||||
interface = ObjectField(InterfaceType)
|
interface = ObjectField(InterfaceType)
|
||||||
interfaces = ObjectListField(InterfaceType)
|
interface_list = ObjectListField(InterfaceType)
|
||||||
|
|
||||||
interface_template = ObjectField(InterfaceTemplateType)
|
interface_template = ObjectField(InterfaceTemplateType)
|
||||||
interface_templates = ObjectListField(InterfaceTemplateType)
|
interface_template_list = ObjectListField(InterfaceTemplateType)
|
||||||
|
|
||||||
inventory_item = ObjectField(InventoryItemType)
|
inventory_item = ObjectField(InventoryItemType)
|
||||||
inventory_items = ObjectListField(InventoryItemType)
|
inventory_item_list = ObjectListField(InventoryItemType)
|
||||||
|
|
||||||
location = ObjectField(LocationType)
|
location = ObjectField(LocationType)
|
||||||
locations = ObjectListField(LocationType)
|
location_list = ObjectListField(LocationType)
|
||||||
|
|
||||||
manufacturer = ObjectField(ManufacturerType)
|
manufacturer = ObjectField(ManufacturerType)
|
||||||
manufacturers = ObjectListField(ManufacturerType)
|
manufacturer_list = ObjectListField(ManufacturerType)
|
||||||
|
|
||||||
platform = ObjectField(PlatformType)
|
platform = ObjectField(PlatformType)
|
||||||
platforms = ObjectListField(PlatformType)
|
platform_list = ObjectListField(PlatformType)
|
||||||
|
|
||||||
power_feed = ObjectField(PowerFeedType)
|
power_feed = ObjectField(PowerFeedType)
|
||||||
power_feeds = ObjectListField(PowerFeedType)
|
power_feed_list = ObjectListField(PowerFeedType)
|
||||||
|
|
||||||
power_outlet = ObjectField(PowerOutletType)
|
power_outlet = ObjectField(PowerOutletType)
|
||||||
power_outlets = ObjectListField(PowerOutletType)
|
power_outlet_list = ObjectListField(PowerOutletType)
|
||||||
|
|
||||||
power_outlet_template = ObjectField(PowerOutletTemplateType)
|
power_outlet_template = ObjectField(PowerOutletTemplateType)
|
||||||
power_outlet_templates = ObjectListField(PowerOutletTemplateType)
|
power_outlet_template_list = ObjectListField(PowerOutletTemplateType)
|
||||||
|
|
||||||
power_panel = ObjectField(PowerPanelType)
|
power_panel = ObjectField(PowerPanelType)
|
||||||
power_panels = ObjectListField(PowerPanelType)
|
power_panel_list = ObjectListField(PowerPanelType)
|
||||||
|
|
||||||
power_port = ObjectField(PowerPortType)
|
power_port = ObjectField(PowerPortType)
|
||||||
power_ports = ObjectListField(PowerPortType)
|
power_port_list = ObjectListField(PowerPortType)
|
||||||
|
|
||||||
power_port_template = ObjectField(PowerPortTemplateType)
|
power_port_template = ObjectField(PowerPortTemplateType)
|
||||||
power_port_templates = ObjectListField(PowerPortTemplateType)
|
power_port_template_list = ObjectListField(PowerPortTemplateType)
|
||||||
|
|
||||||
rack = ObjectField(RackType)
|
rack = ObjectField(RackType)
|
||||||
racks = ObjectListField(RackType)
|
rack_list = ObjectListField(RackType)
|
||||||
|
|
||||||
rack_reservation = ObjectField(RackReservationType)
|
rack_reservation = ObjectField(RackReservationType)
|
||||||
rack_reservations = ObjectListField(RackReservationType)
|
rack_reservation_list = ObjectListField(RackReservationType)
|
||||||
|
|
||||||
rack_role = ObjectField(RackRoleType)
|
rack_role = ObjectField(RackRoleType)
|
||||||
rack_roles = ObjectListField(RackRoleType)
|
rack_role_list = ObjectListField(RackRoleType)
|
||||||
|
|
||||||
rear_port = ObjectField(RearPortType)
|
rear_port = ObjectField(RearPortType)
|
||||||
rear_ports = ObjectListField(RearPortType)
|
rear_port_list = ObjectListField(RearPortType)
|
||||||
|
|
||||||
rear_port_template = ObjectField(RearPortTemplateType)
|
rear_port_template = ObjectField(RearPortTemplateType)
|
||||||
rear_port_templates = ObjectListField(RearPortTemplateType)
|
rear_port_template_list = ObjectListField(RearPortTemplateType)
|
||||||
|
|
||||||
region = ObjectField(RegionType)
|
region = ObjectField(RegionType)
|
||||||
regions = ObjectListField(RegionType)
|
region_list = ObjectListField(RegionType)
|
||||||
|
|
||||||
site = ObjectField(SiteType)
|
site = ObjectField(SiteType)
|
||||||
sites = ObjectListField(SiteType)
|
site_list = ObjectListField(SiteType)
|
||||||
|
|
||||||
site_group = ObjectField(SiteGroupType)
|
site_group = ObjectField(SiteGroupType)
|
||||||
site_groups = ObjectListField(SiteGroupType)
|
site_group_list = ObjectListField(SiteGroupType)
|
||||||
|
|
||||||
virtual_chassis = ObjectField(VirtualChassisType)
|
virtual_chassis = ObjectField(VirtualChassisType)
|
||||||
# TODO: Rectify list field name
|
|
||||||
virtual_chassis_list = ObjectListField(VirtualChassisType)
|
virtual_chassis_list = ObjectListField(VirtualChassisType)
|
||||||
|
@ -1549,8 +1549,6 @@ class VirtualChassisTest(APIViewTestCases.GraphQLTestCase, APIViewTestCases.APIV
|
|||||||
model = VirtualChassis
|
model = VirtualChassis
|
||||||
brief_fields = ['id', 'master', 'member_count', 'name', 'url']
|
brief_fields = ['id', 'master', 'member_count', 'name', 'url']
|
||||||
|
|
||||||
graphql_base_name_plural = 'virtual_chassis_list'
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
site = Site.objects.create(name='Test Site', slug='test-site')
|
site = Site.objects.create(name='Test Site', slug='test-site')
|
||||||
|
@ -6,25 +6,25 @@ from .types import *
|
|||||||
|
|
||||||
class ExtrasQuery(graphene.ObjectType):
|
class ExtrasQuery(graphene.ObjectType):
|
||||||
config_context = ObjectField(ConfigContextType)
|
config_context = ObjectField(ConfigContextType)
|
||||||
config_contexts = ObjectListField(ConfigContextType)
|
config_context_list = ObjectListField(ConfigContextType)
|
||||||
|
|
||||||
custom_field = ObjectField(CustomFieldType)
|
custom_field = ObjectField(CustomFieldType)
|
||||||
custom_fields = ObjectListField(CustomFieldType)
|
custom_field_list = ObjectListField(CustomFieldType)
|
||||||
|
|
||||||
custom_link = ObjectField(CustomLinkType)
|
custom_link = ObjectField(CustomLinkType)
|
||||||
custom_links = ObjectListField(CustomLinkType)
|
custom_link_list = ObjectListField(CustomLinkType)
|
||||||
|
|
||||||
export_template = ObjectField(ExportTemplateType)
|
export_template = ObjectField(ExportTemplateType)
|
||||||
export_templates = ObjectListField(ExportTemplateType)
|
export_template_list = ObjectListField(ExportTemplateType)
|
||||||
|
|
||||||
image_attachment = ObjectField(ImageAttachmentType)
|
image_attachment = ObjectField(ImageAttachmentType)
|
||||||
image_attachments = ObjectListField(ImageAttachmentType)
|
image_attachment_list = ObjectListField(ImageAttachmentType)
|
||||||
|
|
||||||
journal_entry = ObjectField(JournalEntryType)
|
journal_entry = ObjectField(JournalEntryType)
|
||||||
journal_entries = ObjectListField(JournalEntryType)
|
journal_entry_list = ObjectListField(JournalEntryType)
|
||||||
|
|
||||||
tag = ObjectField(TagType)
|
tag = ObjectField(TagType)
|
||||||
tags = ObjectListField(TagType)
|
tag_list = ObjectListField(TagType)
|
||||||
|
|
||||||
webhook = ObjectField(WebhookType)
|
webhook = ObjectField(WebhookType)
|
||||||
webhooks = ObjectListField(WebhookType)
|
webhook_list = ObjectListField(WebhookType)
|
||||||
|
@ -6,31 +6,31 @@ from .types import *
|
|||||||
|
|
||||||
class IPAMQuery(graphene.ObjectType):
|
class IPAMQuery(graphene.ObjectType):
|
||||||
aggregate = ObjectField(AggregateType)
|
aggregate = ObjectField(AggregateType)
|
||||||
aggregates = ObjectListField(AggregateType)
|
aggregate_list = ObjectListField(AggregateType)
|
||||||
|
|
||||||
ip_address = ObjectField(IPAddressType)
|
ip_address = ObjectField(IPAddressType)
|
||||||
ip_addresses = ObjectListField(IPAddressType)
|
ip_address_list = ObjectListField(IPAddressType)
|
||||||
|
|
||||||
prefix = ObjectField(PrefixType)
|
prefix = ObjectField(PrefixType)
|
||||||
prefixes = ObjectListField(PrefixType)
|
prefix_list = ObjectListField(PrefixType)
|
||||||
|
|
||||||
rir = ObjectField(RIRType)
|
rir = ObjectField(RIRType)
|
||||||
rirs = ObjectListField(RIRType)
|
rir_list = ObjectListField(RIRType)
|
||||||
|
|
||||||
role = ObjectField(RoleType)
|
role = ObjectField(RoleType)
|
||||||
roles = ObjectListField(RoleType)
|
role_list = ObjectListField(RoleType)
|
||||||
|
|
||||||
route_target = ObjectField(RouteTargetType)
|
route_target = ObjectField(RouteTargetType)
|
||||||
route_targets = ObjectListField(RouteTargetType)
|
route_target_list = ObjectListField(RouteTargetType)
|
||||||
|
|
||||||
service = ObjectField(ServiceType)
|
service = ObjectField(ServiceType)
|
||||||
services = ObjectListField(ServiceType)
|
service_list = ObjectListField(ServiceType)
|
||||||
|
|
||||||
vlan = ObjectField(VLANType)
|
vlan = ObjectField(VLANType)
|
||||||
vlans = ObjectListField(VLANType)
|
vlan_list = ObjectListField(VLANType)
|
||||||
|
|
||||||
vlan_group = ObjectField(VLANGroupType)
|
vlan_group = ObjectField(VLANGroupType)
|
||||||
vlan_groups = ObjectListField(VLANGroupType)
|
vlan_group_list = ObjectListField(VLANGroupType)
|
||||||
|
|
||||||
vrf = ObjectField(VRFType)
|
vrf = ObjectField(VRFType)
|
||||||
vrfs = ObjectListField(VRFType)
|
vrf_list = ObjectListField(VRFType)
|
||||||
|
@ -6,7 +6,7 @@ from .types import *
|
|||||||
|
|
||||||
class TenancyQuery(graphene.ObjectType):
|
class TenancyQuery(graphene.ObjectType):
|
||||||
tenant = ObjectField(TenantType)
|
tenant = ObjectField(TenantType)
|
||||||
tenants = ObjectListField(TenantType)
|
tenant_list = ObjectListField(TenantType)
|
||||||
|
|
||||||
tenant_group = ObjectField(TenantGroupType)
|
tenant_group = ObjectField(TenantGroupType)
|
||||||
tenant_groups = ObjectListField(TenantGroupType)
|
tenant_group_list = ObjectListField(TenantGroupType)
|
||||||
|
@ -6,7 +6,7 @@ from .types import *
|
|||||||
|
|
||||||
class UsersQuery(graphene.ObjectType):
|
class UsersQuery(graphene.ObjectType):
|
||||||
group = ObjectField(GroupType)
|
group = ObjectField(GroupType)
|
||||||
groups = ObjectListField(GroupType)
|
group_list = ObjectListField(GroupType)
|
||||||
|
|
||||||
user = ObjectField(UserType)
|
user = ObjectField(UserType)
|
||||||
users = ObjectListField(UserType)
|
user_list = ObjectListField(UserType)
|
||||||
|
@ -24,7 +24,7 @@ __all__ = (
|
|||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# REST API Tests
|
# REST/GraphQL API Tests
|
||||||
#
|
#
|
||||||
|
|
||||||
class APITestCase(ModelTestCase):
|
class APITestCase(ModelTestCase):
|
||||||
@ -427,11 +427,13 @@ class APIViewTestCases:
|
|||||||
|
|
||||||
class GraphQLTestCase(APITestCase):
|
class GraphQLTestCase(APITestCase):
|
||||||
|
|
||||||
def _get_graphql_base_name(self, plural=False):
|
def _get_graphql_base_name(self):
|
||||||
if plural:
|
"""
|
||||||
return getattr(self, 'graphql_base_name_plural',
|
Return graphql_base_name, if set. Otherwise, construct the base name for the query
|
||||||
self.model._meta.verbose_name_plural.lower().replace(' ', '_'))
|
field from the model's verbose name.
|
||||||
return getattr(self, 'graphql_base_name', self.model._meta.verbose_name.lower().replace(' ', '_'))
|
"""
|
||||||
|
base_name = self.model._meta.verbose_name.lower().replace(' ', '_')
|
||||||
|
return getattr(self, 'graphql_base_name', base_name)
|
||||||
|
|
||||||
def _build_query(self, name, **filters):
|
def _build_query(self, name, **filters):
|
||||||
type_class = get_graphql_type_for_model(self.model)
|
type_class = get_graphql_type_for_model(self.model)
|
||||||
@ -466,9 +468,9 @@ class APIViewTestCases:
|
|||||||
@override_settings(LOGIN_REQUIRED=True)
|
@override_settings(LOGIN_REQUIRED=True)
|
||||||
def test_graphql_get_object(self):
|
def test_graphql_get_object(self):
|
||||||
url = reverse('graphql')
|
url = reverse('graphql')
|
||||||
object_type = self._get_graphql_base_name()
|
field_name = self._get_graphql_base_name()
|
||||||
object_id = self._get_queryset().first().pk
|
object_id = self._get_queryset().first().pk
|
||||||
query = self._build_query(object_type, id=object_id)
|
query = self._build_query(field_name, id=object_id)
|
||||||
|
|
||||||
# Non-authenticated requests should fail
|
# Non-authenticated requests should fail
|
||||||
with disable_warnings('django.request'):
|
with disable_warnings('django.request'):
|
||||||
@ -491,8 +493,8 @@ class APIViewTestCases:
|
|||||||
@override_settings(LOGIN_REQUIRED=True)
|
@override_settings(LOGIN_REQUIRED=True)
|
||||||
def test_graphql_list_objects(self):
|
def test_graphql_list_objects(self):
|
||||||
url = reverse('graphql')
|
url = reverse('graphql')
|
||||||
object_type = self._get_graphql_base_name(plural=True)
|
field_name = f'{self._get_graphql_base_name()}_list'
|
||||||
query = self._build_query(object_type)
|
query = self._build_query(field_name)
|
||||||
|
|
||||||
# Non-authenticated requests should fail
|
# Non-authenticated requests should fail
|
||||||
with disable_warnings('django.request'):
|
with disable_warnings('django.request'):
|
||||||
@ -511,7 +513,7 @@ class APIViewTestCases:
|
|||||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||||
data = json.loads(response.content)
|
data = json.loads(response.content)
|
||||||
self.assertNotIn('errors', data)
|
self.assertNotIn('errors', data)
|
||||||
self.assertGreater(len(data['data'][object_type]), 0)
|
self.assertGreater(len(data['data'][field_name]), 0)
|
||||||
|
|
||||||
class APIViewTestCase(
|
class APIViewTestCase(
|
||||||
GetObjectViewTestCase,
|
GetObjectViewTestCase,
|
||||||
|
@ -6,16 +6,16 @@ from .types import *
|
|||||||
|
|
||||||
class VirtualizationQuery(graphene.ObjectType):
|
class VirtualizationQuery(graphene.ObjectType):
|
||||||
cluster = ObjectField(ClusterType)
|
cluster = ObjectField(ClusterType)
|
||||||
clusters = ObjectListField(ClusterType)
|
cluster_list = ObjectListField(ClusterType)
|
||||||
|
|
||||||
cluster_group = ObjectField(ClusterGroupType)
|
cluster_group = ObjectField(ClusterGroupType)
|
||||||
cluster_groups = ObjectListField(ClusterGroupType)
|
cluster_group_list = ObjectListField(ClusterGroupType)
|
||||||
|
|
||||||
cluster_type = ObjectField(ClusterTypeType)
|
cluster_type = ObjectField(ClusterTypeType)
|
||||||
cluster_types = ObjectListField(ClusterTypeType)
|
cluster_type_list = ObjectListField(ClusterTypeType)
|
||||||
|
|
||||||
virtual_machine = ObjectField(VirtualMachineType)
|
virtual_machine = ObjectField(VirtualMachineType)
|
||||||
virtual_machines = ObjectListField(VirtualMachineType)
|
virtual_machine_list = ObjectListField(VirtualMachineType)
|
||||||
|
|
||||||
vm_interface = ObjectField(VMInterfaceType)
|
vm_interface = ObjectField(VMInterfaceType)
|
||||||
vm_interfaces = ObjectListField(VMInterfaceType)
|
vm_interface_list = ObjectListField(VMInterfaceType)
|
||||||
|
@ -211,9 +211,7 @@ class VMInterfaceTest(APIViewTestCases.GraphQLTestCase, APIViewTestCases.APIView
|
|||||||
bulk_update_data = {
|
bulk_update_data = {
|
||||||
'description': 'New description',
|
'description': 'New description',
|
||||||
}
|
}
|
||||||
|
|
||||||
graphql_base_name = 'vm_interface'
|
graphql_base_name = 'vm_interface'
|
||||||
graphql_base_name_plural = 'vm_interfaces'
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
|
Loading…
Reference in New Issue
Block a user