python核心编程学习笔记-2016-09-14-03-Web编程(七)
来源:互联网 发布:计算机控制系统的软件 编辑:程序博客网 时间:2024/06/05 00:07
20.7 高级CGI
高级CGI的三个特性:mutipart表单实现的文件上传、CGI字段的多重值和cookie的使用。
20.7.1 multipart表单实现的文件上传(?)
CGI的两种表单编码形式之一,另一种是默认的通过url编码(?)。这种编码的特点?应用?
20.7.2 CGI的多值字段(?)
例子中的多选是多值字段?即lang变量对应一个列表?
20.7.3 cookie
Web站点服务器要求保存在客户端上的二进制数据。本人理解是,再次进入表单页面时,输入框内显示的是自己上一次输入的数据。
服务器向客户端发送一个请求保存cookie,而不必在返回的Web页面中嵌入数据,以此来保存数据。一旦cookie建立,HTTP_COOKIE环境变量会将那些cookie自动放到请求中发给服务器。
cookie是以分号分隔得键值对存在,若要访问这些数据,就要分隔或解析这些字符串。
书中例子:
#-*-coding: utf-8-*-from cgi import FieldStoragefrom os import environ # os.environ可以获取系统的相关信息,在这里是用是因为客户端建立cookie之后,os.environ中的HTTP_COOKIE环境变量会自动将cookie放入请求中发送给服务器from cStringIO import StringIO # StringIO(str)是指在内存中读写字符串,类似于打开文件访问文件中的数据from urllib import quote, unquotefrom string import capwords, strip, split, joinclass AdvCGI(object): header = 'Content-Type: text/html\n\n' # HTTP MIME文件头 url = '/cgi-bin/asvcgi.py' # 文件路径# 在formhtml中,要注意METHOD=post,这表明表单提交的方式是post,如果改成get的话,文件上传会出问题,不明白这是为什么# 在formhtml中的变量有cookie、person、lang和upfile四个变量, formhtml = '''<HTML><HEAD><TITLE>Advanced CGI Demo</TITLE></HEAD><BODY><H2>Advanced CGI Demo Form</H2><FORM METHOD=post ACTION="%s" ENCTYPE="multipart/form-data"><H3>My Cookie Setting</H3><LI><CODE><B>CPPuser = %s</B></CODE><H3>Enter cookie value<BR><INPUT NAME=cookie value="%s"> (<I>optional</I>)</H3><H3>Enter your name<BR><INPUT NAME=person VALUE="%s"> (<I>optional</I>)</H3><H3>What languages can you program in?(<I>at least one required</I>)</H3>%s<H3>Enter file to upload </H3><INPUT TYPE=file NAME=upfile VALUE="%s" SIZE=45><P><INPUT TYPE=submit></FORM></BODY></HTML>''' langSet = ('Python', 'Perl', 'Java', 'C++', 'PHP', 'C', 'Javascript') langItem = '<INPUT TYPE=checkbox NAME=lang VALUE="%s" %s> %s\n' def getCPPCookies(self): # 从客户端中读取cookies,在显示表单页面时会调用该函数 if environ.has_key('HTTP_COOKIE'): # 检测客户端是否有cookie存在,这可以区分该程序是第一次生成表单页面还是再次生成表单页面,这里是再次生成表单页面 for eachCookie in map(strip, split(environ['HTTP_COOKIE'], ';')): # cookie是以';'分隔的键值对存在的,所以必须先解析 if len(eachCookie) > 6 and eachCookie[:3] == 'CPP': # 每一个键值对以'CPP'开头? tag = eachCookie[3:7] # 本例中cookie只有两个键,分别是info和user,所以都是四个字符 try: self.cookies[tag] = eval(unquote(eachCookie[8:])) # 生成cookie时使用了quote(),自然在这里要用unquote() except (NameError, SyntaxError): self.cookies[tag] = unquote(eachCookie[8:]) # 同上 else: # 第一次生成表单页面 self.cookies['info'] = self.cookies['user'] = '' # 第一次生成表单页面,cookie不存在,所以cookies中所有键的值都是'' if self.cookies['info'] != '': # cookie变量不为空,也就是cookie存在,即再次生成表单页面时 self.who, langStr, self.fn = split(self.cookies['info'], ':') # who对应person变量,langStr是lang变量所有选项以','分隔组成的字符串,fn是上传文件名 self.langs = split(langStr, ',') # langs是lang变量选项组成的列表 else: self.who = self.fn = '' # cookie变量为空,即第一次生成表单页面 self.langs = ['Python'] # langs默认至少有'Python'这个元素,即第一次打开表单页面时,'Python'选项已经被选上了 # 显示表单页面 def showForm(self): self.getCPPCookies() # 首先是读取cookie,此时self.who, langStr, self.fn, self.langs依情况取值 langStr = '' # 将form for eachLang in AdvCGI.langSet: if eachLang in self.langs: # 第一次生成表单页面,self.langs = ['Python'],'Python'选项被选上,再次生成表单也是类似 langStr += AdvCGI.langItem % (eachLang, 'CHECKED', eachLang) else: langStr += AdvCGI.langItem % (eachLang, '', eachLang) # 使用cookStatus和userCook来追踪是否有cookie产生,前者在页面上显示cookie状态,后者在程序中显示cookie状态 if not self.cookies.has_key('user') or self.cookies['user'] == '': # 第一次生成表单页面,cookie没有设定,userCook当然也为'' cookStatus = '<I>(cookies has not been set yet)</I>' userCook = '' else: userCook = cookStatus = self.cookies['user'] # 再次生成表单页面,但为什么是'user'这个键? print AdvCGI.header + AdvCGI.formhtml % (AdvCGI.url, cookStatus, userCook, self.who, langStr, self.fn) # 错误页面 errhtml = '''<HTML><HEAD><TITLE>Advanced CGI Demo</TITLE></HEAD><BODY><H3>ERROR</H3><B>%s</B><P><FORM><INPUT TYPE=button VALUE=BackONCLICK="window.history.back()"></FORM></BODY></HTML>''' def showError(self): print AdvCGI.header + AdvCGI.errhtml % (self.error) # 结果页面 reshtml = '''<HTML><HEAD><TITLE>Advanced CGI Demo</TITLE></HEAD><BODY><H2>Your Upload Data</H2><H3>Your cookie value is: <B>%s</B></H3><H3>Your name is: <B>%s</B></H3><H3>You can program in the following languages:</H3><UL>%s</UL><H3>You upload file...<BR>Name: <I>%s</I><BR>Contents:</H3><PRE>%s</PRE>Click <A HREF="%s"><B>here</B></A> to return to form.</BODY></HTML>''' # 设置cookie,并让客户端储存 def setCPPCookies(self): for eachCookie in self.cookies.keys(): print 'Set-Cookie: CPP%s=%s; path=/' % (eachCookie, quote(self.cookies[eachCookie])) # 规定cookie格式,存入HTTP_COOKIE? # 显示结果页面 def doResults(self): MAXBYTES = 1024 langlist = '' # 补全reshtml for eachLang in self.langs: langlist = langlist + '<LI>%s<BR>' % eachLang filedata = '' while len(filedata) < MAXBYTES: # 读取上传的文件,并赋值给filedata变量,前提是不超过1K data = self.fp.readline() if data == '': break filedata += data else: # 超过1K后,之后的内容用...显示 filedata += '... <B><I>(file truncated due to size)</I></B>' self.fp.close() if filedata == '': # 读取文件内容为'', filedata = '<B><I>(file upload error or file not given)</I></B>' filename = self.fn # 文件名 if not self.cookies.has_key('user') or self.cookies['user'] == '': cookStatus = '<I>(cookie has not been set yet)</I>' userCook = '' else: userCook = cookStatus = self.cookies['user'] self.cookies['info'] = join([self.who, join(self.langs, ','), filename], ':') # 设定'info'的值 self.setCPPCookies() print AdvCGI.header + AdvCGI.reshtml % (cookStatus, self.who, langlist, filename, filedata, AdvCGI.url) def go(self): # 程序核心 self.cookies = {} self.error = '' form = FieldStorage() if form.keys() == []: # 第一次生成表单页面 self.showForm() return if form.has_key('person'): self.who = capwords(strip(form['person'].value)) if self.who == '': self.error = 'Your name is required. (blank)' else: self.error = 'Your name is required. (missing)' if form.has_key('cookie'): self.cookies['user'] = unquote(strip(form['cookie'].value)) # 'user'在这里赋值 else: self.cookies['user'] = '' self.langs = [] if form.has_key('lang'): langdata = form['lang'] if type(langdata) == type([]): for eachLang in langdata: self.langs.append(eachLang.value) else: sel.langs.append(langdata.value) else: self.error = 'At least one language required.' if form.has_key('upfile'): upfile = form['upfile'] self.fn = upfile.filename or '' if upfile.file: self.fp = upfile.file else: self.fp = StringIO('(no data)') else: self.fp = StringIO('(no file)') self.fn = '' if not self.error: self.doResults() else: self.showError()if __name__ == "__main__": page = AdvCGI() page.go()
结果与书中相同。cookie还是能理解的,多值字段不是特别明白,mutipart编码就不知道在说什么。
0 0
- python核心编程学习笔记-2016-09-14-03-Web编程(七)
- Python核心编程学习笔记(七)
- python核心编程学习笔记-2016-09-10-03-Web编程(三)
- python核心编程学习笔记-2016-09-14-01-Web编程(五)
- python核心编程学习笔记-2016-09-14-02-Web编程(六)
- python核心编程学习笔记-2016-09-10-01-Web编程(一)
- python核心编程学习笔记-2016-09-10-02-Web编程(二)
- python核心编程学习笔记-2016-09-11-01-Web编程(四)
- python核心编程学习笔记-2016-09-15-02-Web编程(八)
- python核心编程学习(七)
- python核心编程学习笔记-2016-09-03-01-图形化用户界面编程(二)
- python核心编程学习笔记-2016-09-03-02-图形化用户界面编程(三)
- python核心编程学习笔记(一)
- Python核心编程学习笔记(三)
- python核心编程学习笔记(1)
- Python核心编程学习笔记(一)
- Python核心编程学习笔记(二)
- Python核心编程学习笔记(三)
- 第一次使用博客
- LeetCode: Climbing Stairs
- JAVAWEB创建和发送邮件
- 树莓派官方系统超频
- C++ 虚函数表解析
- python核心编程学习笔记-2016-09-14-03-Web编程(七)
- 【ssh】采用强大的intellj IDE实现javaSSH2的搭建
- 18 UI美化之level(等级显示显示)
- 每日总结【2016-09-14】
- (SSM框架)SpringMVC+Spring4+Mybatis+Maven环境快速搭建开发案例
- C++虚析构函数及纯虚析构函数
- 8种基本类型 及 相互转换
- 取原图旋转角度(IOS和Android相机拍的照片) 自动旋转
- Struts2初识