Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

One-level select_related #395

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

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

Successfully merging this pull request may close these issues.

2 participants