Code Kitchen: Overriding and keyword parameters
I hinted, in the first Code Kitchen that there was a bit more to tell of the story of or recent Django refactoring.
Recall that we created a family of filter classes with the superclass doing all the work of returning what we need for our object tree-view, leaving the subclasses to redefine the filter_x() methods to define selection criteria for X, Y and Z objects.
Now, all the objects in our hierarchy have a Boolean deleted attribute, and we never want to display deleted objects. We could specify this easily using Django's filter() method by saying X.objects.filter(deleted=False), but we've chosen to do something slightly more subtle. Class Filter defines our default criteria like this:
class Filter(object):
not_deleted = {'deleted':False}
...
def filter_Xs(self, **criteria ):
criteria.update(self.not_deleted)
return X.objects.filter(**criteria)
Filter's other methods call filter_Xs() (also filter_Ys() and filter_Zs()) with no actual parameters. The method uses the dictionary's update() method to add the 'not deleted' criterion to the empty dictionary which then becomes the actual keyword parameter list for the call to Django's filter() method.
Filter's sub-classes override filter_Xs() (also filter_Ys() and filter_Zs()) to define more specific selection criteria. Though these may be arbitrarily complex, one simple solution is to add more selection criteria to be used by the filter method. Some of our tree filters look like this:
class CountryFilter(Filter):
country = None
def __init__(self,country):
self.country = country
def filter_Xs(self,**criteria):
return super(CountryFilter,self).filter_Xs(country=self.country)
...
Filter's methods look slightly odd at firs sight. But we write them once and, in return, the implementations of many specific filter sub-classes become simple and uncluttered.