OpenDataAlex
OpenDataAlex

Reputation: 1475

Return Django ORM union result in Django-Graphene

I am trying to query two separate objects and return them as a single result set. I've tried using a Union and an Interface, but not sure what I'm doing wrong there.

My model:

class BaseActivity(models.Model):
    class Meta:
        abstract = True

    name = models.CharField(db_column="activity_type_name", unique=True, max_length=250)
    created_at = CreationDateTimeField()
    modified_at = ModificationDateTimeField()
    created_by = models.UUIDField()
    modified_by = models.UUIDField()
    deleted_at = models.DateTimeField(blank=True, null=True)
    deleted_by = models.UUIDField(blank=True, null=True)


class Activity(BaseActivity):
    class Meta:
        db_table = "activity_type"
        ordering = ("sort_order",)

    id = models.UUIDField(
        db_column="activity_type_id",
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    sort_order = models.IntegerField()

    def __str__(self):
        return self.name


class CustomActivity(BaseActivity):
    class Meta:
        db_table = "organization_custom_activity_type"

    id = models.UUIDField(
        db_column="organization_custom_activity_type",
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    farm = models.ForeignKey("farm.Farm", db_column="organization_id", on_delete=models.DO_NOTHING, related_name="custom_activity_farm")

My schema:

class FarmActivities(graphene.ObjectType):
    id = graphene.String()
    name = graphene.String()


class ActivityType(DjangoObjectType):
    class Meta:
        model = Activity
        fields = ("id", "name", "requires_crop", "sort_order")



class CustomActivityType(DjangoObjectType):
    class Meta:
        model = CustomActivity
    fields = ("id", "name", "farm")

And the query:

class Query(graphene.ObjectType):
    get_farm_activities = graphene.Field(FarmActivities, farm=graphene.String(required=True))

    def resolve_get_farm_activities(self, info, farm):

        farm_activities = Activity.objects.values("id", "name").filter(
            farmtypeactivityrel__farm_type__farm=farm, deleted_at=None
        )

        custom_activities = CustomActivity.objects.values("id", "name").filter(farm=farm, deleted_at=None)

        return list(chain(farm_activities, custom_activities))

With this, I do get a list back from the query, but it's not going thru the resolver when I call getFarmActivities.

Literally the list returns:

ExecutionResult(data={'getFarmActivities': {'id': None, 'name': None}}, errors=None)

Upvotes: 2

Views: 439

Answers (1)

OpenDataAlex
OpenDataAlex

Reputation: 1475

How to resolve graphene.Union Type?

That provided the hint I needed to get this working. I had to build a Union that would parse the model and not the schema type.

class FarmActivities(graphene.Union):
    class Meta:
        types = (ActivityType, CustomActivityType)

    @classmethod
    def resolve_type(cls, instance, info):
        if isinstance(instance, Activity):
            return ActivityType
        if isinstance(instance, CustomActivity):
            return CustomActivityType

        return FarmActivities.resolve_type(instance, info)

Which then allowed me to run the query like so:

def resolve_get_farm_activities(self, info, farm):

farm_activities = Activity.objects.filter(
    farmtypeactivityrel__farm_type__farm=farm
)

custom_activities = CustomActivity.objects.filter(farm=farm)

return list(chain(farm_activities, custom_activities))

And the API query:

    query farmParam($farm: String!)
    {
        getFarmActivities(farm: $farm)
        {
            ... on CustomActivityType
            {
                id
                name
            }
            ... on ActivityType
            {
                id
                name
            }
        }
    }

Upvotes: 1

Related Questions