ASP and Python
How Python integrates w/ASP
Active Server Pages has been a useful addition to Microsoft's Web
strategy. Because of the language neutral nature of COM, any language
that is capable of "Active X" (meaning COM) scripting can integrate
with it. Python, with it's excellent COM support, is one of those
languages. When you install it, by default, it is not setup for the
ASP enviroment with IIS. If you look at the html documentation in:
C:\\Program Files\\Python\\win32com\\HTML\\index.html at the bottom of the
page you'll see 'Active X Scripting Demos'. If you then click on that
it will describe how to register the engire. Essentially, there is a
program called pyscript.py in:
C:\\Program Files\\Python\\win32comext\\axscript\\client
and if you run that it should register python for the ASP environment.
Microsoft typically positions vbscript in the IIS role. Vbscript
is adequate for many tasks, but is a very simplified language. Python
is a very rich and powerful language offering things like true
exception handleing, OOP style programming, excellent win32 access,
easy persistence w/pickle, etc. And, being multi-platform, you can
leverage the language in other web environments. You will also find
many ASP code examples in Vbscript are easily converted into python.
There is a slight difference with setting values with Application and
Session Objects. In cases where you'd see: Session('Key')= TheValue,
you'd translate to Session.SetValue('Key', TheValue) for python. This
is because vbscript makes it look like you are assigning something to
a function call which python does not support.
Another thing ASP allows you to do is to mix code and HTML. Thus,
you need some way to tell the server that the following is code. Since
python is not used by default, you need to set your page to use
it. You can do that by having the first line say: <%@ LANGUAGE
=Python%>. Then after that point, anything between '<%' and '%>'
delimeters will run as python code. Everything else will be treated as
HTML. It is important to note that a python loop ends in the python
block -- they don't extend past intervening html to the next block. For
me that normally isn't an issue, since I do not like mixing code and
html. Prefering a clean split of code and html, I generally
generate webpages using templates all in python w/HTMLgen. Take a look
at: http://www.python.org/topics/web/HTML.html for available resources
w/HTML. An very basic page would look like:
Example
Basic Python ASP page:
<%@ LANGUAGE = Python%> <HTML> <head></head> <body> <h1>Querying database</h1> <% #do some python stuff here #import libraries, etc. for i in query_database(): Response.Write('output of results converted to a string') %> </body> </html>If you use HTMLgen's template, then it could look like:
<%@ LANGUAGE = Python%> <% #notice no raw HTML at all. We instead use a template html file #generated however you want (perhaps frontpage) that substitutes #anything delimeted by {} for output from our python. In this case #text {mid} in the template is substituted for results. import HTMLgen import HTMLcolors results='<h1>Querying database</h1>' for i in query_database(): results=results+str(i) ###################### #Here we are using a template dictionary #to substitute the text {mid} found in the template file #for results T=HTMLgen.TemplateDocument(/path/template_file.html) T.substitutions['mid']=results # here is where our results went!! webpage=str(T) Response.Write(webpage) %>For one page this is overkill. However, for developing many pages, something like this allows you to ignore the grunt work of making pages and helps to keep them consistent. HTMLgen also gives you other useful tools worth looking into.
The ASP model has several 'collection' objects: Request, Response,
Session, Application, and ObjectContext. The Request collection has
things like data returned from web forms(GET or POST) and environment
variables. The Response object is the opposite of the Request object
it deals with sending data back to the client, since you cannot do a
simple 'print'. Next, the Application collection allows programs to
globally store/share information for your site. The Session object
allows one to store per-user state. And, finally the Objectcontext
object is for use with MTS. We'll focus on the basics, Request and
Response.
Typically, you can treat these objects like simple versions of a python
dictionary or list. A good way to get an idea of what they have is to
print out their entire contents. Here is a simple function that
converts your server (environment) variables into a python dictionary:
def getenv (): d_env={} #initialize dictionary for key in Request.ServerVariables: d_env[key]=str(Request.ServerVariables(key)) return d_envRequest.ServerVariables responds to the python operator 'in' by returning a list. And, it can also take a key and return it's value. You notice the value is converted into a string, so it can be treated like a python string.
For a more complicated example, here is a python function that
converts the Request.Form or Request.Querystring objects into a python
dictionary. This would be a function you'd use to get back data from a
form. It returns either the entire Request Collection as a python
dictionary, a subset if you provide a list of keys, or a single value,
if you provide a single key.
Get Request collection - 3 different ways to get Request data
def getdata (keys=''): ''' ] possible ways to call this function: value=getdata('key') dict=getdata(('key1','key2')) #get subset dict=getdata() #return everything It assumes you don't have the same key for GET and POST methods ''' import types key_type=type(keys) d_data={} #initialize dictionary if keys=='': #if they don't supply keys then return everything for key in Request.Form: d_data[key]=Request.Form(key) for key in Request.QueryString: d_data[key]=Request.QueryString(key) return d_data elif key_type == types.StringType: #if they provide a single string value=Request.Form(keys) if (value != 'None') and (str(value) == 'None'): return Request.QueryString(keys) else: return value #if they provide a list then return a dictionary with all the key/values elif key_type == types.TupleType or key_type == types.ListType: for key in keys: value=Request.Form(key) #now check if the data was empty, if so look at QueryString if (value != 'None') and (str(value) == 'None'): value=Request.QueryString(key) data[key]=value return d_dataTo print out this data you will need to use the Response object which accepts python strings. A simple: Response.Write(str(d_data)) would suffice. A better looking way would be to do something like:
for pair in d_data.items(): Response.Write(pair[0]+':'+pair[1]+'<br>')Notice the adding of <br> to have a line break for each pair. If you want it more fancy you can convert it to table output.
HTMLgen can help with it's Table object:
Table=HTMLgen.Table('Key/Value pairs for Response object') #title Table.heading=('Key','Value') for pair in d_data.items() #get each key/val pair Table.body.append(list(pair)) #takes a list of lists #[ [key1,val1], [key2,val2]] #one pair for every table row Response.Write(str(Table))HTMLgen deserves an entire article to itself. You can use it to write web forms and manage other HTML elements. As a final example, here is a simple ASP application that uses the functions written above and a simple HTMLgen web form to spit data back. The typical idiom w/HTMLgen is to create a web object like a form and append things to it. In the code below, I append a textbox, radio buttons, and a checkbox.
<%@ LANGUAGE = Python%> <% from HTMLgen import * from HTMLcolors import * #import the file which has getenv and getdata from above d_env=getenv() #get environment variables #create a simple default document webpage = SimpleDocument(title = 'Bedrock Housing') #create form and append elements to it F=Form(d_env['URL']) F.append(Heading(1,'Rock Housing')) F.append('What Street:',BR()) F.append( Input(type='text',name='street',size=30),BR()) F.append('Select your house type:',BR()) types=('limestone','granite','marble') for i in types: F.append(Input(type='radio',name='house_type',rlabel=i,value=i),BR()) F.append('Select special features:',BR()) features=('stone roof','dishwasher','door bell') for i in features: F.append(Input(type='checkbox',name='features',rlabel=i,value=i),BR()) #done with web form, now append it webpage.append(F) #get the data the user entered and return it results=getdata() #get everything webpage.append(str(results)) Response.Write(str(webpage))Have a great time with programming with python!
John Nielsen nielsenjf@my-deja.com