Simple HTML template modules?

Gerhard W. Gruber sparhawk at gmx.at
Fri Jan 26 06:41:46 EST 2001


Rayed Al-Rashed wrote:

> I am trying to build CGI programs using Python, and I searched for
> simple HTML templates modules but couldn't find any ... any ideas
> where I can find such module.

I have written a module exactly for this purpose. I hope this is of some
help to you. Usage is rather simple. If you have questions you can
contact me at the address below.

-- 
Bye,
   Gerhard

CocoNet GmbH Erkrath
email: gerhard.gruber at coconet.de
privat: sparhawk at gmx.at

If you think education is expensive, try ignorance!
-------------- next part --------------
#!/usr/local/bin/python
#
# (C) by Gerhard W. Gruber in Vienna 2000
# All rights reserved.
#
# This file is placed under the terms of GPL (GNU Public Licence) and is to be
# used in accordance. Please refer to the GPL for licence information.
#
# You can contact the author at sparhawk at aon.at.
	

# system includes
import os
import string

""" Template class provides functions to work with templates. A template file
    is simply a [text]files which has variables in it which can (and should) be
	substituted to a desired text. A substitution can be a simple string or the
	result from another templatefile. This class was primarily written to
	support working with dynamic HTML files from GCI programs but it can be used
	fo any kind of textsubstituion. I used it in another project for
	printermasks or standardized email documents. Since I didn't anything
	involving HTML in this code, the possibilites are up to you with no
	constraints in regard to your project. :)
	For usage of the functions please refer to the function headers.
"""

class Template:
# ---------------------------------- __init__ ----------------------------------
	""" __init__: constructor for base class Template.
	       fn: Array with the filenames of the template files.
		       The array is a twodimensional array. Each entry must contain a
			   pair of names. The first name is the filename and the second
			   is the alias for that file. This way you can use the same file
			   more than once with different aliases if you need to assign the
			   same template different values in a single document.
	"""
	def __init__(self, fn):
		self.Files = {}
		
		for i in fn:
			self.Files[i[1]] = self.CreateTemplate(i[0])

# ---------------------------------- __repr__ ----------------------------------
	""" __repr__: Selfrepresentation of the class
	"""
	def __repr__(self):
		return self.DumpClass();

# ----------------------------------- __str__ ----------------------------------
	""" __str__: Stringrepresentation of the class
	"""
	def __str__(self):
		return self.DumpClass();

# --------------------------------- DumpClass ----------------------------------
	""" DumpClass: Selfrepresentation of the class
	"""
	def DumpClass(self):
		s = "TemplateClass:\n"
		for i in self.Files.keys():
			s = s + i + ": " + self.Files[i]["FILE"] + "\n"
			for vn in self.Files[i]["VAR"].keys():
				if self.Files[i]["VAR"][vn] == None:
					s = s + "   " + vn + " = None\n"
				else:
					s = s + "   " + vn + " = " + self.Files[i]["VAR"][vn] + "\n"
			
		return s

# ------------------------------- CreateTemplate -------------------------------
	""" CreateTemplate: constructs a template structure for a single filename.
	    The file is parsed for variables and an array is constructed, containing
		the variable names and it's content (fiiled out later by the user).

		The filenames must be passed in an array which contains two entries per
		file. An alias that is used as a shortcut for the file and the filename
		itself. This way you can use a templatefile multiple times in the same
		program in case you need to assign different values for a template in
		the same run (in case a template appears multiple times) and it is also
		more convenient to use a short name instead of the filename itself.

		The filestructure is a dictionary that contains the following entries:
		FILENAME: name of the templatefile
		TEXT: the content of the templatefile
		VAR: Dictionary with the variablenames as key and its current content
		     as value.
		VARPOS: Array that contains all positions of variables in the file with
		        start- and endposition. The position includes the '$' sign and
				the curly braces as well, so you have to remove them to get the
				actual variablename. The VAR key contains the names including
				these characters because it doesn't matter for the lookup and
				it's easier to lookup the name because you don't have to remove
				them.
	"""
	def CreateTemplate(self, name):
		# define a file maintainence structure
		file = { "FILE":name, "VAR":None, "TEXT":"", "VARPOS":[] }

		# variablenames go here
		varnames = {}
		offset = 0
		start = 0
		end = 0

		fl = open(name)
		while 1:
			ln = fl.readline()

			# break on EOF
			if not ln:
				break

			file["TEXT"] = file["TEXT"]+ln
			ln_len = len(ln)
			state = 0

			for i in xrange(ln_len):
				if state == 2 and ln[i] == "}":
					# endposition of the variable
					end = offset + i + 1

					# state reset to variable searchmode
					state = 0
					varnames[file["TEXT"][start:end]] = None
					file["VARPOS"].append({ "START":start,"END":end })

				# A variable is only found when the '{' is right after
				# the '$'.
				if state == 1:
					if start == (offset + (i-1)) and ln[i] == "{":
						# position of the variable (starting at '$')
						state = 2
					else:
						# not a "{" or not immediatly after the "$" sign
						# so we reset to initial state.
						state = 0
					
				if state == 0 and ln[i] == "$":   # could be a variable
					start = offset + i
					state = 1

			# increase the current offset to the next line
		   	offset = offset + ln_len

		fl.close()

		# assign the variablenames to the filestructure
		file["VAR"] = varnames

		# print file["TEXT"][file["VARPOS"][0]["START"]:file["VARPOS"][0]["END"]]
		return file


# ---------------------------------- SetValue ----------------------------------
	""" SetValue: Assign a value to a variable in a given file. The file is
	    idientified by its alias and not by its filename.

		file: Alias for the template file
		var:  Variablename that gets the value
		val:  Value that is to be assigned to the variable
	"""
	def SetValue(self, file, var, val):
		return self.AppendValue(file, var, val, 0)

# -------------------------------- AppendValue ---------------------------------
	""" AppendValue: Appends a value to a variable in a given file. The file is
	    idientified by its alias and not by its filename.

		file: Alias for the template file
		var:  Variablename that gets the value
		val:  Value that is to be assigned to the variable
		mode: If set to 1 the value is appended to the current value of the
		      variable, 0 means it is set as new value.

	    If mode is set to 0 the behaviour is the same as using SetValue().
	"""
	def AppendValue(self, file, var, val, mode=1):
		fl = self.Files[file]
		varname = "${"+var+"}"
		if mode == 0 or fl["VAR"][varname] == None:
			fl["VAR"][varname] = val
		else:
			fl["VAR"][varname] = fl["VAR"][varname] + val

# ---------------------------------- GetValue ----------------------------------
	""" GetValue: Returns the value of a variable in a given file.

		file: Alias for the template file
		var:  Variablename that gets the value
	"""
	def GetValue(self, file, var):
		fl = self.Files[file]
		varname = "${"+var+"}"
		return fl["VAR"][varname]

# ----------------------------------- GetFile ----------------------------------
	""" GetFile: Returns the content of a file whit all variables substituted
	    for their current values.

		file: Alias for the template file

		If a variable contains None as it's value, the variable is copied
		verbatim to the output string.
	"""
	def GetFile(self, file):
		fl = self.Files[file]
		s = ""
		s_pos = 0

		for pos in fl["VARPOS"]:
			start = pos["START"]
			end = pos["END"]
			var = fl["TEXT"][start:end]   # variablename
			val = fl["VAR"][var]          # it's value

			# if the value of the variable is None, the variablename is
			# copied verbatim to the file.
			if val == None:
				val = var

			s = s + fl["TEXT"][s_pos:start] + val
			s_pos = end

		s = s + fl["TEXT"][s_pos:len(fl["TEXT"])]

		return s


if __name__ == '__main__':
	tpl = Template([
		[ "/usr/local/http/public_html/cdadmin/tpl/qo_menu.tpl", "MENU" ],
		[ "/usr/local/http/public_html/cdadmin/tpl/qo_menu.t", "MENUT" ],
		[ "/usr/local/http/public_html/cdadmin/tpl/qo_boxentry.tpl", "ENTRY" ],
		[ "/usr/local/http/public_html/cdadmin/tpl/qo_boxstatus.tpl", "STATUS" ]
	])

	tpl.SetValue("ENTRY", "OWNER_KEY_VAL", "Testvalue1")
	tpl.AppendValue("ENTRY", "OWNER_KEY_VAL", " Testvalue2")
	tpl.SetValue("ENTRY", "OWNER_VAL", "Testvalue3")
	tpl.AppendValue("MENU", "OWNER_BOX", tpl.GetFile("ENTRY"))

	tpl.SetValue("ENTRY", "OWNER_KEY_VAL", "Testvalue4")
	tpl.AppendValue("ENTRY", "OWNER_KEY_VAL", " Testvalue5")
	tpl.SetValue("ENTRY", "OWNER_VAL", "Testvalue6")
	tpl.AppendValue("MENU", "OWNER_BOX", tpl.GetFile("ENTRY"))

	print tpl.GetFile("MENU")

	# print tpl



More information about the Python-list mailing list