views:

32

answers:

1

I've got a module pagetypes.py that extracts a couple of constants (I shouldn't really use word constant here) from the db for later reuse:

def _get_page_type_(type):
    return PageType.objects.get(type=type)

PAGE_TYPE_MAIN = _get_page_type_('Main')
PAGE_TYPE_OTHER = _get_page_type_('Other')

then somewhere in views I do:

import pagetypes
...
print pagetypes.PAGE_TYPE_MAIN #simplified

It all works fine when db has those records and I make sure it does... unless this code is under test. In that case I want to load those records into db via fixtures. The problem with that is that fixtures are not loaded (even syncdb is not run) by the time pagetypes module is imported resulting in _get_page_type_ call failing with:

psycopg2.ProgrammingError: relation "pagetype" does not exist

Test runner always tries to import pagetypes module, because it is imported by view that is under test.

How do I get around this problem?

I was thinking of lazily loading pagetype constants PAGE_TYPE_MAIN, PAGE_TYPE_OTHER, but then I want it to fail early if those records are not in the db (or fixtures if under test), so I don't really know how to implement this.

I was also thinking of object level caching and just call PageType.objects.get(type=type) whenever constant is used/called, but wouldn't that be an overkill? Calling orm without cache would result in too many db calls, which I want to prevent.

It must be something very simple, but I can't work it out. ;-)

+2  A: 

I would use the functions instead of the constants, but memoize them:

_cache = {}

def get_page_type(type_name):
    if type_name not in _cache:
        _cache[type_name] = PageType.objects.get(type=type_name)
    return _cache[type_name]

So now you'd call get_page_type('Main') directly when necessary.

Daniel Roseman
That's pretty clever and simple.
googletorp
I've slightly modified your code to do less typing every time I want to use page type constant:`PAGE_TYPE_MAIN = property(lambda: get_page_type('Main'))`I used some code from http://stackoverflow.com/questions/880530/can-python-modules-have-properties-the-same-way-that-objects-can to make `property` work on module level. Works fine, thanks!
parxier