Fetching BasicInfo, BillingInfo, and DocumentInfo objects The repetition is super obvious here. How can I rewrite this code? I need one base method in which I pass a Django model, to call objects.filter, but I can't figure out how to do it.

from profiles.models import BasicInfo, BillingInfo, DocumentInfo

__author__ = 'vol'


class BasicInfoService:
    def __init__(self):
        pass

    @staticmethod
    def get_by_profile_id(profile_id, is_versioned):
        if is_versioned:
            return BasicInfo.objects.filter(profile_id=profile_id).order_by('-version')
        return BasicInfo.objects.filter(profile_id=profile_id).order_by('-version')[:1][0]


class BillingInfoService:
    def __init__(self):
        pass

    @staticmethod
    def get_by_profile_id(profile_id, is_versioned):
        if is_versioned:
            return BillingInfo.objects.filter(profile_id=profile_id).order_by('-version')
        return BillingInfo.objects.filter(profile_id=profile_id).order_by('-version')[:1][0]


class DocumentInfoService:
    def __init__(self):
        pass

    @staticmethod
    def get_by_profile_id(profile_id, is_versioned):
        if is_versioned:
            return DocumentInfo.objects.filter(profile_id=profile_id).order_by('-version')
        return DocumentInfo.objects.filter(profile_id=profile_id).order_by('-version')[:1][0]
The template method pattern seems useful here:


Create a base class with a get_by_profile_id method that calls a get_queryset method to get the at appropriate QuerySet object to work with
The base class doesn't implement get_queryset, it's the job of the subclasses. This is the template method


Something along the lines of this in the base class:

def get_by_profile_id(self, profile_id, is_versioned):
    queryset = self.get_queryset().filter(profile_id=profile_id).order_by('-version')
    if is_versioned:
        return queryset
    return queryset[:1][0]


And in the subclass for BasicInfo:

def get_queryset(self):
    return BasicInfo.objects


Notice that I eliminated another duplication in the following and ordering logic. Note that Djangi will not execute the query until elements are accessed in the query set, so when I initialize queryset before the if condition, that doesn't hit the database.