Sfoglia il codice sorgente

8245 add graphql filtering at all levels (#10618)

* 8245 monkey-patch graphene-django to support filtering at all levels

* 8245 fix tests

* 8245 fix tests
Arthur Hanson 3 anni fa
parent
commit
99cf1b1671

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

@@ -27,7 +27,7 @@ class CustomFieldType(ObjectType):
 
     class Meta:
         model = models.CustomField
-        fields = '__all__'
+        exclude = ('content_types', )
         filterset_class = filtersets.CustomFieldFilterSet
 
 
@@ -83,5 +83,5 @@ class WebhookType(ObjectType):
 
     class Meta:
         model = models.Webhook
-        fields = '__all__'
+        exclude = ('content_types', )
         filterset_class = filtersets.WebhookFilterSet

+ 49 - 3
netbox/netbox/graphql/__init__.py

@@ -1,9 +1,13 @@
 import graphene
-from graphene_django.converter import convert_django_field
-from taggit.managers import TaggableManager
-
 from dcim.fields import MACAddressField, WWNField
+from django.db import models
+from graphene import Dynamic
+from graphene_django.converter import convert_django_field, get_django_field_description
+from graphene_django.fields import DjangoConnectionField
 from ipam.fields import IPAddressField, IPNetworkField
+from taggit.managers import TaggableManager
+
+from .fields import ObjectListField
 
 
 @convert_django_field.register(TaggableManager)
@@ -21,3 +25,45 @@ def convert_field_to_tags_list(field, registry=None):
 def convert_field_to_string(field, registry=None):
     # TODO: Update to use get_django_field_description under django_graphene v3.0
     return graphene.String(description=field.help_text, required=not field.null)
+
+
+@convert_django_field.register(models.ManyToManyField)
+@convert_django_field.register(models.ManyToManyRel)
+@convert_django_field.register(models.ManyToOneRel)
+def convert_field_to_list_or_connection(field, registry=None):
+    """
+    From graphene_django.converter.py we need to monkey-patch this to return
+    our ObjectListField with filtering support instead of DjangoListField
+    """
+    model = field.related_model
+
+    def dynamic_type():
+        _type = registry.get_type_for_model(model)
+        if not _type:
+            return
+
+        if isinstance(field, models.ManyToManyField):
+            description = get_django_field_description(field)
+        else:
+            description = get_django_field_description(field.field)
+
+        # If there is a connection, we should transform the field
+        # into a DjangoConnectionField
+        if _type._meta.connection:
+            # Use a DjangoFilterConnectionField if there are
+            # defined filter_fields or a filterset_class in the
+            # DjangoObjectType Meta
+            if _type._meta.filter_fields or _type._meta.filterset_class:
+                from .filter.fields import DjangoFilterConnectionField
+
+                return DjangoFilterConnectionField(_type, required=True, description=description)
+
+            return DjangoConnectionField(_type, required=True, description=description)
+
+        return ObjectListField(
+            _type,
+            required=True,  # A Set is always returned, never None.
+            description=description,
+        )
+
+    return Dynamic(dynamic_type)

+ 0 - 5
netbox/netbox/settings.py

@@ -18,11 +18,6 @@ from sentry_sdk.integrations.django import DjangoIntegration
 
 from netbox.config import PARAMS
 
-# Monkey patch to fix Django 4.0 support for graphene-django (see
-# https://github.com/graphql-python/graphene-django/issues/1284)
-# TODO: Remove this when graphene-django 2.16 becomes available
-django.utils.encoding.force_text = force_str  # type: ignore
-
 
 #
 # Environment setup