def test_model_wo_filterset(self): schema = generate_schema_type(app_name="wrong_app", model=ChangeLoggedModel) self.assertEqual(schema.__bases__[0], DjangoObjectType) self.assertEqual(schema._meta.model, ChangeLoggedModel) self.assertIsNone(schema._meta.filterset_class)
def setUp(self): self.datas = ( { "field_name": "my_text", "field_type": CustomFieldTypeChoices.TYPE_TEXT }, { "field_name": "my new field", "field_type": CustomFieldTypeChoices.TYPE_TEXT, }, { "field_name": "my_int1", "field_type": CustomFieldTypeChoices.TYPE_INTEGER, }, { "field_name": "my_int2", "field_type": CustomFieldTypeChoices.TYPE_INTEGER, }, { "field_name": "my_bool_t", "field_type": CustomFieldTypeChoices.TYPE_BOOLEAN, }, { "field_name": "my_bool_f", "field_type": CustomFieldTypeChoices.TYPE_BOOLEAN, }, { "field_name": "my_date", "field_type": CustomFieldTypeChoices.TYPE_DATE }, { "field_name": "my_url", "field_type": CustomFieldTypeChoices.TYPE_URL }, ) obj_type = ContentType.objects.get_for_model(Site) # Create custom fields for Site objects for data in self.datas: cf = CustomField.objects.create(type=data["field_type"], name=data["field_name"], required=False) cf.content_types.set([obj_type]) self.schema = generate_schema_type(app_name="dcim", model=Site)
def generate_query_mixin(): """Generates and returns a class definition representing a GraphQL schema.""" logger.info("Beginning generation of Nautobot GraphQL schema") class_attrs = {} def already_present(model): """Check if a model and its resolvers are staged to added to the Mixin.""" single_item_name = str_to_var_name(model._meta.verbose_name) list_name = str_to_var_name(model._meta.verbose_name_plural) if single_item_name in class_attrs: logger.warning( f"Unable to register the schema single type '{single_item_name}' in GraphQL, " f"there is already another type {class_attrs[single_item_name]._type} registered under this name" ) return True if list_name in class_attrs: logger.warning( f"Unable to register the schema list type '{list_name}' in GraphQL, " f"there is already another type {class_attrs[list_name]._type} registered under this name" ) return True return False logger.debug( "Generating dynamic schemas for all models in the models_features graphql registry" ) # - Ensure an attribute/schematype with the same name doesn't already exist registered_models = registry.get("model_features", {}).get("graphql", {}) for app_name, models in registered_models.items(): for model_name in models: try: # Find the model class based on the content type ct = ContentType.objects.get(app_label=app_name, model=model_name) model = ct.model_class() except ContentType.DoesNotExist: logger.warning( f"Unable to generate a schema type for the model '{app_name}.{model_name}' in GraphQL," "this model doesn't have an associated ContentType, please create the Object manually." ) continue type_identifier = f"{app_name}.{model_name}" if type_identifier in registry["graphql_types"].keys(): # Skip models that have been added statically continue schema_type = generate_schema_type(app_name=app_name, model=model) registry["graphql_types"][type_identifier] = schema_type logger.debug("Adding plugins' statically defined graphql schema types") # After checking for conflict for schema_type in registry["plugin_graphql_types"]: model = schema_type._meta.model type_identifier = f"{model._meta.app_label}.{model._meta.model_name}" if type_identifier in registry["graphql_types"]: logger.warning( f'Unable to load schema type for the model "{type_identifier}" as there is already another type ' "registered under this name. If you are seeing this message during plugin development, check to " "make sure that you aren't using @extras_features(\"graphql\") on the same model you're also " "defining a custom GraphQL type for.") else: registry["graphql_types"][type_identifier] = schema_type logger.debug( "Extending all registered schema types with dynamic attributes") for schema_type in registry["graphql_types"].values(): if already_present(schema_type._meta.model): continue schema_type = extend_schema_type(schema_type) class_attrs.update(generate_attrs_for_schema_type(schema_type)) QueryMixin = type("QueryMixin", (object, ), class_attrs) logger.info("Generation of Nautobot GraphQL schema complete") return QueryMixin
def test_model_w_filterset(self): schema = generate_schema_type(app_name="dcim", model=Device) self.assertEqual(schema.__bases__[0], DjangoObjectType) self.assertEqual(schema._meta.model, Device) self.assertEqual(schema._meta.filterset_class, DeviceFilterSet)
def setUp(self): self.schema = generate_schema_type(app_name="dcim", model=Site)
def setUp(self): site_ct = ContentType.objects.get_for_model(Site) rack_ct = ContentType.objects.get_for_model(Rack) vlan_ct = ContentType.objects.get_for_model(VLAN) self.m2m_1 = Relationship.objects.create( name="Vlan to Rack", slug="vlan-rack", source_type=rack_ct, source_label="My Vlans", destination_type=vlan_ct, destination_label="My Racks", type="many-to-many", ) self.m2m_2 = Relationship.objects.create( name="Another Vlan to Rack", slug="vlan-rack-2", source_type=rack_ct, destination_type=vlan_ct, type="many-to-many", ) self.o2m_1 = Relationship.objects.create( name="generic site to vlan", slug="site-vlan", source_type=site_ct, destination_type=vlan_ct, type="one-to-many", ) self.o2o_1 = Relationship.objects.create( name="Primary Rack per Site", slug="primary-rack-site", source_type=rack_ct, source_hidden=True, destination_type=site_ct, destination_label="Primary Rack", type="one-to-one", ) self.sites = [ Site.objects.create(name="Site A", slug="site-a"), Site.objects.create(name="Site B", slug="site-b"), Site.objects.create(name="Site C", slug="site-c"), ] self.racks = [ Rack.objects.create(name="Rack A", site=self.sites[0]), Rack.objects.create(name="Rack B", site=self.sites[1]), Rack.objects.create(name="Rack C", site=self.sites[2]), ] self.vlans = [ VLAN.objects.create(name="VLAN A", vid=100, site=self.sites[0]), VLAN.objects.create(name="VLAN B", vid=100, site=self.sites[1]), VLAN.objects.create(name="VLAN C", vid=100, site=self.sites[2]), ] self.schema = generate_schema_type(app_name="dcim", model=Site)
def generate_query_mixin(): """Generates and returns a class definition representing a GraphQL schema.""" class_attrs = {} def already_present(model): """Check if a model and its resolvers are staged to added to the Mixin.""" single_item_name = str_to_var_name(model._meta.verbose_name) list_name = str_to_var_name(model._meta.verbose_name_plural) if single_item_name in class_attrs: logger.warning( f"Unable to register the schema type '{single_item_name}' in GraphQL from '{app_name}':'{model_name}'," "there is already another type registered under this name") return True if list_name in class_attrs: logger.warning( f"Unable to register the schema type '{list_name}' in GraphQL from '{app_name}':'{model_name}'," "there is already another type registered under this name") return True # Generate SchemaType Dynamically for all Models registered in the model_features registry # - Ensure an attribute/schematype with the same name doesn't already exist registered_models = registry.get("model_features", {}).get("graphql", {}) for app_name, models in registered_models.items(): for model_name in models: try: # Find the model class based on the content type ct = ContentType.objects.get(app_label=app_name, model=model_name) model = ct.model_class() except ContentType.DoesNotExist: logger.warning( f"Unable to generate a schema type for the model '{app_name}.{model_name}' in GraphQL," "this model doesn't have an associated ContentType, please create the Object manually." ) continue type_identifier = f"{app_name}.{model_name}" if type_identifier in registry["graphql_types"].keys(): # Skip models that have been added statically continue schema_type = generate_schema_type(app_name=app_name, model=model) registry["graphql_types"][type_identifier] = schema_type # Add all objects in the plugin registry to the main registry # After checking for conflict for schema_type in registry["plugin_graphql_types"]: model = schema_type._meta.model type_identifier = f"{model._meta.app_label}.{model._meta.model_name}" if type_identifier not in registry["graphql_types"].keys(): registry["graphql_types"][type_identifier] = schema_type # Extend schema_type with dynamic attributes for all object defined in the registry for schema_type in registry["graphql_types"].values(): if already_present(schema_type._meta.model): continue schema_type = extend_schema_type(schema_type) class_attrs.update(generate_attrs_for_schema_type(schema_type)) QueryMixin = type("QueryMixin", (object, ), class_attrs) return QueryMixin