I’ve always disliked having to write __repr__ methods for my classes. It isn’t hard, it is just tedious. In Django, it is especially important to make them, since the admin pages use that method when listing objects from the data model.
However, since Python allows classes to have multiple inheritance, I have long since made a helper “Mixin” class to remove most of the pain from writing my __repr__ methods. If you haven’t heard the term, a “Mixin” is a class which adds functionality to classes which inherit from it. The philosophy is that it shouldn’t change base functionality, thus avoiding many of the problems with multiple inheritance.
Philosophy aside, mixins can be extremely useful, and I love this one.I use it to provide a default __repr__ and to add a utility method which makes writing custom __repr__ methods extremely easy.
Example use
This is from the model for my Invisible Castle RPG site:
class Roll((models.Model, FormatterMixin):
[… model code here …]>
def __repr__(self):
return self.make_repr(”Roll: “, ‘id’, ‘name’, ‘dice’, ‘rolls’, ‘results’)
Isn’t that nice? It makes the roll objects automatically have a repr which looks something like this: “Roll: id=1, name=example, dice=1d6, rolls=1, results=3″
If I had entirely omitted the __repr__ function above, it would still return: “Roll: id=1″
The mixin
"""
Utility functions for nicely formatting django models
:Author: Bruce Kroeze
:Contact: brucek@solidsitesolutions.com
:Copyright: Bruce Kroeze (c) 2006
:License: LGPL
Classes:
- `FormatterMixin`: A class which helps its implementers make nice looking __repr__ methods.
Functions:
- `get_field`: Get a field from an object, trying both the named property and its
"get_" version.
"""
__docformat__ = 'restructuredtext'
class FormatterMixin(object):
"""A class which helps its implementers make nice looking __repr__ methods.
"""
def get_field(self, field, fallback=None):
"""Get a field from this object, trying both the named property and its
"get_" version.
Parameters:
- `field`: to look up
- `fallback`: default value
Returns:
- field value
"""
return get_field(self, field, fallback)
def make_repr(self, title, *args):
"""Create a string using the fields requested.
Parameters:
- `self`
- `title`: to put at the beginning of the string
- `args`: a list of fields to put in the string
Returns:
- string
"""
rep = [title]
rep.extend(["%s=%s, " % (field, self.get_field(field, "ATTRIBUTE MISSING"))
for field in args])
ret = "".join(rep)
if (ret.endswith(", ")):
ret = ret[:-2]
return ret
def __repr__(self):
return self.make_repr(self.__class__.__name__, 'id')
def get_field(obj, field, fallback=None):
"""Get a field from this object, trying both the named property and its
"get_" version.
Parameters:
- `obj`
- `field`: to look up
- `fallback`: default value
Returns:
- field value
"""
try:
# simple object property
return obj.__dict__[field]
except KeyError:
pass
try:
# class property
return obj.__getattribute__(field)
except AttributeError:
pass
# getter
getter = 'get_%s' % field
try:
func = obj.__getattribute__(getter)
return func()
except AttributeError:
pass
return fallback
Technorati Tags: python, mixin class, django
















0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment