jazzband/django-model-utils

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

mortenthansen opened this issue · 0 comments

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

`