GraphQL-like features in Django Rest Framework

This page summarizes the projects mentioned and recommended in the original post on dev.to

Scout Monitoring - Free Django app performance insights with Scout Monitoring
Get Scout setup in minutes, and let us sweat the small stuff. A couple lines in settings.py is all you need to start monitoring your apps. Sign up for our free tier today.
www.scoutapm.com
featured
InfluxDB - Power Real-Time Data Analytics at Scale
Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
www.influxdata.com
featured
  • graphene-django

    Build powerful, efficient, and flexible GraphQL APIs with seamless Django integration.

  • it swallows errors, making debugging a mess

  • Scout Monitoring

    Free Django app performance insights with Scout Monitoring. Get Scout setup in minutes, and let us sweat the small stuff. A couple lines in settings.py is all you need to start monitoring your apps. Sign up for our free tier today.

    Scout Monitoring logo
  • drf-flex-fields

    Dynamically set fields and expand nested resources in Django REST Framework serializers.

  • import difflib import importlib import logging from functools import lru_cache from django.db.models import ForeignKey, ManyToManyField from rest_flex_fields.serializers import FlexFieldsModelSerializer SERIALIZERS_DIR = "myapp.api.serializers" class MagicFlexFieldsModelSerializer(FlexFieldsModelSerializer): """ Magically expands all related fields by inspecting related fields for a model. """ def __init__(self, *args, **kwargs): self.expandable_fields = discover_expandable_fields(self.Meta.model) super().__init__(*args, **kwargs) def discover_expandable_fields(model): """ Magically assigns `expandable_fields` from all related model fields. Discovers the serializer class based on the related model name. Assigns expandable_fields: The end result looks like this: ``` { 'created_by': backend.api.serializers.user_serializer.UserSerializer, 'workspace': backend.api.serializers.workspace_serializer.WorkspaceSerializer, 'users': (backend.api.serializers.user_serializer.UserSerializer, {'many': True}), 'archived_by': (backend.api.serializers.user_serializer.UserSerializer, {'many': True}), 'notified': (backend.api.serializers.user_serializer.UserSerializer, {'many': True}), 'conversation_messages': (backend.api.serializers.message_serializer.MessageSerializer, {'many': True}) } ``` See the example at: https://github.com/rsinger86/drf-flex-fields?tab=readme-ov-file#quick-start """ expandable_fields = {} serializer_classes = find_serializer_classes() for field in model._meta.get_fields(): if isinstance(field, (ForeignKey, ManyToManyField)): related_model_name = field.related_model.__name__ serializer_cls = find_closest_matching_serializer_by_name( related_model_name, serializer_classes ) if field.related_model != serializer_cls.Meta.model: logging.debug( f"Unable to find the correct serializer class for: {field.related_model}" ) continue if isinstance(field, ForeignKey): expandable_fields[field.name] = serializer_cls else: expandable_fields[field.name] = ( serializer_cls, {"many": True}, ) for field in model._meta.related_objects: related_model_name = field.related_model.__name__ serializer_cls = find_closest_matching_serializer_by_name( related_model_name, serializer_classes ) if field.related_model != serializer_cls.Meta.model: logging.debug( f"Unable to find the correct serializer class for: {field.related_model}" ) continue accessor_name = field.get_accessor_name() expandable_fields[accessor_name] = (serializer_cls, {"many": True}) return expandable_fields def find_closest_matching_serializer_by_name(input_str, serializer_classes): matcher = difflib.SequenceMatcher(None, input_str, str(serializer_classes[0])) closest_match = serializer_classes[0] max_similarity = matcher.ratio() for cls in serializer_classes[1:]: matcher = difflib.SequenceMatcher(None, input_str, str(cls)) similarity = matcher.ratio() if similarity > max_similarity: closest_match = cls max_similarity = similarity return closest_match @lru_cache(maxsize=None) def find_serializer_classes(): """ Technically you could get this from the DRF router object via the registered views. """ init_module = importlib.import_module(SERIALIZERS_DIR) serializer_classes = [ getattr(init_module, name) for name in dir(init_module) if callable(getattr(init_module, name)) and "Serializer" in name ] return serializer_classes

  • blog-examples

  • Below is an example of an app with a user model and a many-to-many relation to an organization model (a user could be a member of many organizations). I've created an example repository to demo the implementation, but below is a snippet.

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts

  • Webhook notifications -> unable to save custom messages

    1 project | /r/ansible | 6 Dec 2023
  • AWX / cicso.nxos Module Help

    1 project | /r/awx | 6 Dec 2023
  • Can someone help me understand CSRF security? (context inside)

    1 project | /r/django | 25 Sep 2023
  • [homelab] I am confused with how 3rd-party GUIs interact with my Ansible server

    1 project | /r/ansible | 6 Jul 2023
  • Social authentication in django rest framework.

    1 project | /r/django | 2 Jul 2023