📄 webpage.py
字号:
#
# Base WebPage object
#
# $Revision: 15 $
# $Date: 8/03/01 12:59p $
#
import os
import dtuple
import cgi
import mx.DateTime
import cachequery
class dbsource:
def __init__(self, source, type='mx'):
self.source = source
if type == 'mx':
import mx.ODBC.Windows as odbc
self.conn = odbc.connect(source, "promuser", "promuser")
elif type == 'odbc':
import odbc
self.conn = odbc.odbc(source)
elif type == 'gf':
import gadfly
self.conn = gadfly.gadfly(source, "gadfly")
else:
raise ValueError, "Illegal data source type %s" % type
self.cursor = self.conn.cursor()
def close(self):
self.cursor.close()
self.conn.close()
class FormsMixin:
def DropDown(self, tbl, valcol, descol, name="pulldown",
default="Please make a selection", selected=None, ordercol=None, autosubmit=None):
"""Create a dropdown selector from two columns of a database table.
Note that column aliasing is used to give fixed attribute names to
the columns retrieved, so this algorithm works with two different
database columns or the same one for both value and description."""
td = dtuple.TupleDescriptor([("ValCol",), ("DesCol",)])
if autosubmit:
auto = """OnChange="submit(this.parent)"""
else:
auto = ""
result = ["""<SELECT NAME="%s" %s ">""" % (name, auto)]
result.append(self.Option("", default))
stmt = "SELECT %s, %s FROM %s" % (valcol, descol, tbl)
if ordercol:
stmt += " ORDER BY %s" % ordercol
# print stmt
self.cursor.execute(stmt)
rows = self.cursor.fetchall()
for row in rows:
row = dtuple.DatabaseTuple(td, row)
result.append(self.Option(row.ValCol, row.DesCol))
result.append("</SELECT>\n")
return "\n".join(result)
def Option(self, val, dsc):
return """<OPTION VALUE="%s">%s""" % (val, dsc)
class Page:
"""Object to implement common behavior. No actual look-and-feel here."""
def __init__(self, dbsource, op, path, query):
"""Build the main page content."""
self.dbsource = dbsource
self.cursor = dbsource.cursor
self.op = op
self.path = path
self.query = query
def Title(self):
return "Page requires Title() method"
def NavBar(self):
return "Page requires NavBar() method"
def Content(self):
return "Page requires Content() method"
def Generate(self):
return \
"""HTTP/1.0 200 OK Response Follows
Content-Type: text/html
Cache-Control: no-cache
<HTML>
<HEAD>
<TITLE>%s</TITLE>
</HEAD>
<BODY>
<TABLE>
<tr>
<td VALIGN="TOP"><IMG SRC="/Image/py.gif"></td><td VALIGN="TOP"><H3><font color="red">Web/Database Technology Demonstrator</font></H3></td>
</tr>
<tr><td colspan="2"><hr></td></tr>
<tr>
<td valign="TOP" width="80">%s</td>
<td valign="TOP" width="250">%s</td>
</tr>
</TABLE>
</BODY>
""" % (self.Title(), self.NavBar(), self.Content())
#
# Global queries to optimize database access
#
q = cachequery.CacheQuery
conn = dbsource("prom2000").conn
qDepts = q("department", "DptCode DptName".split(), (), conn, ORDER=("DptName",), refresh=30)
class Home(Page):
def Title(self):
return "Welcome to the Database Mini-Web!"
def NavBar(self):
"""Generate nav bar for any department page."""
result = ["""<FONT size="-2">"""]
for DptCode, DptName in qDepts(debug=1):
result.append("""<A HREF="/DeptHome/%s">%s</A><BR><BR>""" % (DptCode, DptName))
result.append("""</FONT>""")
return "\n".join(result)
def Content(self):
if self.op.upper() == "GET":
text = """<H1 color="red">There's a Database Behind this Site!</H1>
<H3>Data source is %s</H3>
<P>Please select a department</P>""" % self.dbsource.source
else:
text = "Sorry. The operation you requested is invalid."
return text
class DeptPage(Page):
def __init__(self, *args, **kw):
# print "args:", args
# print "kw:", kw
Page.__init__(self, *args, **kw)
DptNames = ["Code", "Name", "Welcome", "Links", "LnksTxt"]
DptDtuple = dtuple.TupleDescriptor([ [colname, ] for colname in DptNames]) # local, could factor out?
if len(self.path) == 0 or self.path[0] == "None":
# XXX this is rather unsatisfactory, and needs changing
self.DptCode = None
self.dpt = dtuple.DatabaseTuple(DptDtuple, [ None for name in DptNames])
else:
#
# XXX Because every subtype also does all this work we are
# XXX definitely reapeating code that should not be repeated
#
self.DptCode = self.path[0]
self.path = self.path[1:] # XXX Need _shftpth() method!
stmt = "SELECT %s FROM department WHERE DptCode=?" % ", ".join(["Dpt"+name for name in DptNames])
# print "SQL:", stmt
self.cursor.execute(stmt, (self.DptCode, ))
r = self.cursor.fetchall()
assert len(r) == 1
self.dpt = dtuple.DatabaseTuple(DptDtuple, r[0])
now = mx.DateTime.today()
stmt = """SELECT DptCode, newsitem.NwsNum, NwsHead FROM newsitem, deptnews
WHERE DptCode=?
AND deptnews.NwsNum=newsitem.NwsNum
AND ? BETWEEN NewsItem.NwsStart AND NewsItem.NwsEnd"""
self.cursor.execute(stmt, (self.dpt.Code, now))
self.Nws = self.cursor.fetchall()
stmt = """SELECT LnkURL, LnkText FROM links WHERE DptCode=?"""
self.cursor.execute(stmt, (self.dpt.Code, ))
self.Lnk = self.cursor.fetchall()
stmt = """SELECT QodHook, QodQuestion, QodAlist, QodAnswer
FROM Qod WHERE ? BETWEEN QodDate AND QodDate+1
AND DptCode = ?
AND QodShow"""
self.cursor.execute(stmt, (now, self.dpt.Code))
self.Qod = self.cursor.fetchall()
def Title(self):
return "Department %s" % self.dpt.Name
def NavBar(self):
"""Generate nav bar for any department page."""
result = ["""<FONT size="-2">"""]
result.append("""<A HREF="/">HOME</A><BR><BR>""")
result.append("""<A HREF="/DeptHome/%s">Dept Home</A><BR><BR>""" % self.DptCode)
if len(self.Nws):
# XXX Departmental news
result.append("""<A HREF="/DeptNews/%s">News</A><BR><BR>""" % self.dpt.Code)
if self.dpt.LnksTxt:
result.append("%s<BR><BR>" % self.dpt.LnksTxt)
if len(self.Lnk):
# XXX Departmental links page link
result.append("""<A HREF="/DeptLinks/%s">More Links</A><BR><BR>""" % self.dpt.Code)
if len(self.Qod):
# Departmental question of the day
result.append("""<B>Today's question:</B><BR><BR>
<A HREF="/DeptQod/%s">%s ...</A><BR><BR>""" % (self.dpt.Code, self.Qod[0][0]))
result.append("""</FONT>""")
return "\n".join(result)
def DeptHeader(self):
return "<P><B>%s</B></BR><HR>" % self.dpt.Name
class DeptHome(DeptPage):
def Content(self):
if self.op.upper() == "GET":
text = self.DeptHeader() + self.dpt.Welcome
else:
text = "Sorry. The operation you requested is invalid."
return text
class DeptLinks(DeptPage):
def Links(self):
result = ["""<BR><P><FONT SIZE="-1">"""]
for row in self.Lnk:
result.append("""<A HREF="http://%s">%s</A><HR>""" % row)
result.append("""</FONT></P>""")
return "\n".join(result)
def Content(self):
if self.op.upper() == "GET":
text = "%s<B>%s</B></P>%s" % (self.DeptHeader(), "Additional Links", self.Links())
else:
text = "Sorry. The operation you requested is invalid."
return text
class DeptNews(DeptPage):
def News(self):
result = ["""<BR><P>"""]
for row in self.Nws:
result.append("""<A HREF="/DeptNewsItem/%s/%s">%s</A><BR><BR>""" % row)
result.append("""<FONT></P>""")
return "\n".join(result)
def Content(self):
if self.op.upper() == "GET":
text = self.DeptHeader()+"<B>%s</B><BR>%s" % ("News", self.News())
else:
text = "Sorry. The operation you requested is invalid."
return text
class DeptNewsItem(DeptPage):
def Content(self):
stmt = "SELECT NwsHead, NwsCopy from newsitem WHERE NwsNum=?"
self.cursor.execute(stmt, (self.path[0], ))
rows = self.cursor.fetchall()
assert len(rows) == 1
NwsHead, NwsCopy = rows[0]
return self.DeptHeader()+"<B><I>%s</I></B><br>%s" % (NwsHead, NwsCopy)
class DeptQod(DeptPage):
def Content(self):
result = [self.DeptHeader(),
"""<B><I>Question of the Day</I></B><BR><BR>%s<BR><BR>%s<BR><BR>""" %
self.Qod[0][1:3]]
result.append("""<A HREF="/DeptQodAns/%s">Click for the answer</A>""" % self.dpt.Code)
return "\n".join(result)
class DeptQodAns(DeptPage):
def Content(self):
return """%s<B><I>Answer of the Day</I></B><BR><BR>%s<BR><BR>""" % \
(self.DeptHeader(), self.Qod[0][3])
class DeptPgPage(DeptPage):
def Content(self):
self.PgpSetName = self.path[0] # XXX need insurance against short path!
self.PtxSetNum = self.path[1]
self.path = self.path[2:] # XXX Need _shftpth() method?
stmt = """SELECT PtxLinkText, PtxSetNum, PtxLink FROM PageText
WHERE PgpSetName=?
ORDER BY PtxSetNum"""
self.cursor.execute(stmt, (self.PgpSetName, ))
linkdata = self.cursor.fetchall()
stmt = """SELECT PtxTitle, PtxContent FROM PageText
WHERE PgpSetName=?
AND PtxSetNum=?"""
# print "SQL:", stmt
self.cursor.execute(stmt, (self.PgpSetName, self.PtxSetNum))
self.PtxTitle, self.PtxContent = self.cursor.fetchall()[0]
# XXX should check that the page group+number actually exists
result = [self.DeptHeader(), '<font size="-2"><center>']
links = []
for PtxLinkText, PtxSetNum, PtxLink in linkdata:
if not PtxLink:
PtxLink = "DeptPgPage"
if PtxSetNum != self.PtxSetNum:
links.append('<A HREF="/%s/%s/%s/%s">%s</A>' % (PtxLink, self.DptCode, self.PgpSetName, PtxSetNum, PtxLinkText))
else:
links.append(PtxLinkText)
result.append(" | ".join(links)) # XXX need sensible multiline behavior here
result.append('</center></font>')
result.append("<BR><HR>%s" % (self.PtxContent))
return "\n".join(result)
imgtype = {
".jpg": "image/jpeg",
".gif": "image/gif",
".png": "image/png"
}
class Image(Page):
#
# Note that image inherits NavBar(), etc., methods, but its
# Generate() never calls them. __init__() is all that is needed!
#
def Generate(self):
if self.op.upper() != "GET":
return \
"""HTTP/1.0 405 You can't post to an image\r\n\r\n"""
else:
fname = self.path[-1]
ext = os.path.splitext(fname)[1]
if imgtype.has_key(ext):
mimetype = imgtype[ext]
else:
return \
"""HTTP/1.0 415 Do not support this image type\r\n\r\n"""
try:
f = open(os.sep.join(["images"] + self.path), "rb")
img = f.read()
return \
"""HTTP/1.0 200 OK Image per request
Content-Type: %s
Content-Length: %s
%s""" % (mimetype, len(img), img)
except IOError:
return \
"""HTTP/1.0 404 Not found\r\n\r\n"""
class ErrorPage(Page):
def Title(self):
return "Program Error"
def NavBar(self):
return "LINK TO REPORT ERRORS?"
def Content(self):
return "<H2>Program Error:</H2><BR>%s" % self.Message()
def Message(self):
return "Unspecified problem"
class ErrorPageIllegalPageType(ErrorPage):
def Message(self):
return "Illegal page type"
#################################################################
if __name__ == "__main__":
page = Page(dbpages.dbsource("departments", "mx"), "GET", "this/is/the/path?with=query")
print page.DropDown("newsitem", "NwsNum", "NwsHead", name="MyDropDown")
print page.Content("GET", ["one", "two", "three"], "Well, hello")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -