September 3, 2010

Django Formatter Mixin Class

GuitarI’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

[tags]python,mixin class,django[/tags]

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay

Related posts:

  1. A Django Killer App – Web Table Data Yet another great use for Django is to make trivial...
  2. Helpful Django utilities and links Two simple links which have been very helpful in doing...
  3. Another win for Django One nice thing about Django is that unlike many frameworks,...
  4. Django Magic Removal, this time for real Despite my earlier initial successes using the Django Magic-Removal Branch,...
  5. Django on Rimuhosting This is just a quick post to confirm that Django...

About Bruce Kroeze

Speak Your Mind

*