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

Inheritance improvments: Select subclasses of foreign relations + get subclass of model fields #543

Open
mortenthansen opened this issue Nov 9, 2022 · 0 comments

Comments

@mortenthansen
Copy link

mortenthansen commented Nov 9, 2022

Problem

I wanted to do single query SQL selects of foreign key relations that are using Django model inheritance and found the following two improvements helpful.

Let me know what you think.

Code examples

Improvement to InheritanceQuerySet that is able to select inherited fields of foreign key relationship. Note that this works with multi-level inheritance by letting field_name be a tuple of list of names.

`
class InheritanceQuerySet(ModelUtilsInheritanceQuerySet):

def select_field_subclasses(self, field_name):
    # Get field name iterable
    if isinstance(field_name, str):
        field_names = (field_name,)
    else:
        field_names = field_name

    # Lookup model
    model = self.model
    for field_name in field_names:
        field = model._meta.get_field(field_name)
        model = field.related_model

    # Lookup subclasses
    subclasses = self._get_subclasses_recurse(model)

    # Construct query
    subclasses = ['%s__%s' % ('__'.join(field_names), subclass) for subclass in subclasses]

    return self.select_related(*subclasses)

`

Using proper select queries with the above method, subclasses of foreign key relations can be retrieved with the following Model Mixin without touching the database.

`
class InheritanceMixin:

def get_subclass(self):
    # Lookup subclasses
    helper = InheritanceQuerySetMixin() # hack to re-use private method of mixin
    subclasses = helper._get_subclasses_recurse(self.__class__)
    
    # Look for existing subclass
    for subclass in subclasses:
        try:
            return getattr(self, subclass)
        except getattr(self.__class__, subclass).RelatedObjectDoesNotExist:
            pass

    return self

`

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

No branches or pull requests

1 participant