HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythondjangoMinor

Fetching BasicInfo, BillingInfo, and DocumentInfo objects

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
objectsanddocumentinfobasicinfofetchingbillinginfo

Problem

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]

Solution

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.

Code Snippets

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]
def get_queryset(self):
    return BasicInfo.objects

Context

StackExchange Code Review Q#93717, answer score: 2

Revisions (0)

No revisions yet.