Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
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
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    def setUp(self):

        self.schema = generate_schema_type(app_name="dcim", model=Site)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
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