strawberry-graphql / strawberry-django

Strawberry GraphQL Django extension
MIT License
396 stars 115 forks source link

How to use django model types with federation? #59

Open uroybd opened 2 years ago

uroybd commented 2 years ago

I want to use Django models with the strawberry federation. But seems like the type methods are conflicting.

Any pointers?

Upvote & Fund

Fund with Polar

uroybd commented 2 years ago

I've solved the problem using this:

# federated_django.py
import strawberry
from strawberry.arguments import UNSET
from strawberry_django import auto
from strawberry_django.type import StrawberryDjangoType, get_fields
from strawberry.annotation import StrawberryAnnotation
from typing import List

def process_type(cls, model, *, filters=UNSET, pagination=UNSET, order=UNSET, keys: List[str] = None, extend: bool = False, **kwargs):
    original_annotations = cls.__dict__.get('__annotations__', {})

    django_type = StrawberryDjangoType(
        origin=cls,
        model=model,
        is_input=kwargs.get('is_input', False),
        is_partial=kwargs.pop('partial', False),
        is_filter=kwargs.pop('is_filter', False),
        filters=filters,
        order=order,
        pagination=pagination,
    )

    fields = get_fields(django_type)

    # update annotations and fields
    cls.__annotations__ = cls_annotations = {}
    for field in fields:
        annotation = field.type \
            if field.type_annotation is None \
            else field.type_annotation.annotation
        if annotation is None:
            annotation = StrawberryAnnotation(auto)
        cls_annotations[field.name] = annotation
        setattr(cls, field.name, field)

    strawberry.type(cls, federation=strawberry.object_type.FederationTypeParams(
        keys=keys or [], extend=extend), **kwargs)

    # restore original annotations for further use
    cls.__annotations__ = original_annotations
    cls._django_type = django_type

    return cls

def type(model, *, filters=UNSET, keys: List[str] = None, extend: bool = False, **kwargs):
    if 'fields' in kwargs or 'types' in kwargs:
        from strawberry_django.legacy.type import type as type_legacy
        return type_legacy(model, **kwargs)

    def wrapper(cls):
        return process_type(cls, model, filters=filters, keys=keys, extend=extend, **kwargs)

    return wrapper
la4de commented 2 years ago

@uroybd, nice! Would you like to contribute, add test and create a pull request? :)