Skip to content

One-level select_related #395

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

OskarPersson
Copy link

This is an attempt at adding support for select_related and thus closing #198. So far it has no unit tests or documentation and has mostly been tested with Graphene-Django which is where I found my need for this.

(Getting graphene-django-optimizer to work with this is the next step!)

With my limited testing it seems to work at the first level (e.g. Parent.objects.select_related('childa__related')) but not any deeper than that (e.g. Parent.objects.select_related('childa__related__childb'))

This PR is not in a mergeable state and instead is currently mostly created for bringing the discussion further for implementing select_related with a more complete solution.

@ADR-007
Copy link

ADR-007 commented Mar 21, 2020

You can try something like that:

from typing import List

from polymorphic.models import PolymorphicModel
from polymorphic.query import PolymorphicQuerySet


class SelectRelatedPolymorphicQuerySet(PolymorphicQuerySet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.used_select_related_cache = False

    def use_select_related(self):
        qs = self._clone()
        qs.used_select_related_cache = True

        return qs

    def _clone(self, *args, **kwargs):
        qs = super()._clone(*args, **kwargs)
        qs.used_select_related_cache = self.used_select_related_cache

        return qs

    def _get_real_instances(self, base_result_objects: List[PolymorphicModel]):
        if self.used_select_related_cache:
            return [item.get_real_instance() for item in base_result_objects]

        return super()._get_real_instances(base_result_objects)
from polymorphic.managers import PolymorphicManager
from polymorphic.models import PolymorphicModel

from vas.utils.models.polymorhic.querysets import SelectRelatedPolymorphicQuerySet


class SelectRelatedPolymorphicModel(PolymorphicModel):
    class Meta:
        abstract = True

    objects = PolymorphicManager.from_queryset(SelectRelatedPolymorphicQuerySet)()

    def get_real_instance(self):
        real_model = self.get_real_instance_class()

        if real_model == self.__class__:
            return self

        # allow to use cache:
        # return getattr(self, real_model.__name__.lower())
        return self._state.fields_cache[real_model.__name__.lower()]  # todo

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants