views:

128

answers:

3

Situation:

I am writing a basic templating system in Python/mod_python that reads in a main HTML template and replaces instances of ":value:" throughout the document with additional HTML or db results and then returns it as a view to the user.

I am not trying to replace all instances of 1 substring. Values can vary. There is a finite list of what's acceptable. It is not unlimited. The syntax for the values is [colon]value[colon]. Examples might be ":gallery: , :related: , :comments:". The replacement may be additional static HTML or a call to a function. The functions may vary as well.

Question:

What's the most efficient way to read in the main HTML file and replace the unknown combination of values with their appropriate replacement?


Thanks in advance for any thoughts/solutions,

c

+4  A: 

There are dozens of templating options that already exist. Consider genshi, mako, jinja2, django templates, or more.

You'll find that you're reinventing the wheel with little/no benefit.

Travis Bradshaw
+1  A: 

If you can't use an existing templating system for whatever reason, your problem seems best tackled with regular expressions:

import re

valre = re.compile(r':\w+:')

def dosub(correspvals, correspfuns, lastditch):
  def f(value):
    v = value.group()[1:-1]
    if v in correspvals:
      return correspvals[v]
    if v in correspfuns:
      return correspfuns[v]()  # or whatever args you need
    # what if a value has neither a corresponding value to
    # substitute, NOR a function to call?  Whatever...:
    return lastditch(v)
  return f

replacer = dosub(adict, another, somefun)

thehtml = valre.sub(replacer, thehtml)

Basically you'll need two dictionaries (one mapping values to corresponding values, another mapping values to corresponding functions to be called) and a function to be called as a last-ditch attempt for values that can't be found in either dictionary; the code above shows you how to put these things together (I'm using a closure, a class would of course do just as well) and how to apply them for the required replacement task.

Alex Martelli
I can't find any documentation for `re.sub()` that takes `function, source`, where the function is provided the string of the match. Where did you come across this usage?
Ipsquiggle
It's described in the documentation for `re.sub()` (http://docs.python.org/library/re.html#re.sub). "If repl is a function, it is called for every non-overlapping occurrence of pattern. The function takes a single match object argument, and returns the replacement string."
jamessan
Right, so in this instance, `value` is a match object, and `value[1:-1]` would fail. Should be `value.group()[1:-1]` I think.
Ipsquiggle
Ah, right. Good catch.
jamessan
@lpsquiggle, you're right, tx -- fixing now.
Alex Martelli
A: 

This is probably a job for a templating engine and for Python there are a number of choices. In this stackoveflow question people have listed their favourites and some helpfully explain why: What is your single favorite Python templating engine?

Tendayi Mawushe