Head First Python(Web开发)

来源:互联网 发布:软件系统功能分析 编辑:程序博客网 时间:2024/05/10 19:26

把程序放在Web上

Web应用有以下特点:

  1. 能够访问你的网站的每一个人都可以使用这个程序。
  2. 位于Web服务器上的某个位置。
  3. 需要更新功能是很容易更新。
Web请求作为某个用户交互的结果由Web浏览器发送到Web服务器。在Web服务器上,会生成Web响应并发回到Web浏览器。整个过程可以总结为5个步骤。

  • 用户在他选择的Web浏览器中输入一个Web地址,选择一个超链接,或者点击一个按钮
  • Web浏览器将用户的动作转换为一个Web请求,并通过互联网把他发送到一个服务器
  • Web服务器收到Web请求,必须决定接下来做什么
  • Web服务器处理Web请求,创建一个Web响应,通过互联网发送给等待着的Web浏览器
  • Web浏览器接收到Web响应,并显示在用户的屏幕上

第4步(可能)有很多子步骤:Web服务器要找到所有执行的程序、执行找到的程序,然后捕捉程序的输出作为Web响应......发回Web浏览器。这个动态生成内容的过程,称为通用网关接口(Common Gateway Interface,CGI),符合这个标准的程序称为CGI脚本。

Web应用需要做什么

可能需要3个Web页面:一个”欢迎“页面、一个”选择选手“页面、一个”显示时间“页面。

采用MVC设计Web应用

好的Web应用应当遵循模型-视图-控制器(Model-View-Control)模式。

  1. 模型:存储(以及及时处理)Web应用数据的代码
  2. 视图:格式化和显示Web应用用户界面的代码
  3. 控制器:将Web应用”粘合“在一起并提供业务逻辑的代码

为数据建模

Web服务器需要存储数据的一个副本。这里的数据就是Kelly教练的计时值。

启动Web应用时,需要把文本文件中的数据转换为AthleteList对象实例,存储在一个字典中,然后保存为pickle文件。这个功能放在put_to_store()函数中。

运行Web应用时,pickle文件中的数据可以作为一个字典供应用使用。这个功能放在get_from_store()函数中。

<span style="font-size:18px;">def put_to_store(files_list):    all_athletes={}    for each_file in files_list:        ath=get_coach_data(each_file)        all_athletes[ath.name]=ath    try:        with open ('athletes.pickle', 'wb') as athf:            pickle.dump(all_athletes,athf)    except IOError as ioerr:        print('File error (put_and_stroe): '+str(ioerr))    return(all_athletes)def get_from_store():    all_athletes={}    try:        with open('athletes.pickle', 'rb') as athf:            all_athletes=pickle.load(athf)    except IOError as ioerr:        print('File error (get_from_store): '+str(ioerr))    return(all_athletes)</span>
将代码键入一个IDLE编辑窗口,并把代码保存到一个文件夹中。按下F5将代码导入IDLE shell,然后使用dir()命令确认导入成功。

<span style="font-size:18px;">>>>> dir()['AthleteList', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', 'get_coach_data', 'get_from_store', 'pickle', 'put_to_store']</span>
创建一个要处理的文件列表,然后调用put_to_store()函数将文件列表中的数据转换成一个字典,存储在pickle中:

<span style="font-size:18px;">>>> the_files=['sarah2.txt','james2.txt','mikey2.txt','julie2.txt']>>> data=put_to_store(the_files)>>> data{'James Lee': ['2-34', '3:21', '2.34', '2.45', '3.01', '2:01', '2:01', '3:10', '2-22', '2-01', '2.01', '2:16'], 'Mikey McManus': ['2:22', '3.01', '3:01', '3.02', '3:02', '3.02', '3:22', '2.49', '2:38', '2:40', '2.22', '2-31'], 'Sarah Sweeney': ['2:58', '2.58', '2:39', '2-25', '2-55', '2:54', '2.18', '2:55', '2:55', '2:22', '2-21', '2.22'], 'Julie Jones': ['2.59', '2.11', '2:11', '2:23', '3-10', '2-23', '3:10', '3.21', '3-21', '3.01', '3.02', '2:59']}</span>
使用字典中现有的数据显示各个选手的名字和出生日期:

<span style="font-size:18px;">>>> for each_athlete in data:print(data[each_athlete].name+''+data[each_athlete].dob)James Lee2002-3-14Mikey McManus2002-2-24Sarah Sweeney2002-6-17Julie Jones2002-8-17</span>
使用get_from_store()函数将腌制数据加载到另一个字典中:

>>> data_copy=get_from_store()>>> for each_athlete in data_copy:print(data_copy[each_athlete].name+''+data_copy[each_athlete].dob)James Lee2002-3-14Mikey McManus2002-2-24Sarah Sweeney2002-6-17Julie Jones2002-8-17
查看界面

视图代码创建Web应用的用户界面(user interface,UI)。用户界面用Web的标记技术HTML来创建。

YATE是一个包括一些生成HTML的辅助函数的模版。

<span style="font-size:18px;">from string import Template从标准库的"string"模块导入"Template"类。它支持简单的字符串替换模版。def start_response(resp="text/html"):    return('Content-type: ' + resp + '\n\n')这个函数需要一个(可选的)字符串作为参数,用它来创建一个CGI"Content-type:"行,参数缺省值是"text/html"。def include_header(the_title):    with open('templates/header.html') as headf:        head_text = headf.read()    header = Template(head_text)    return(header.substitute(title=the_title))这个函数需要一个字符串作为参数,用在HTML页面最前面的标题中。页面本身存储在一个单独的文件"templates/header.html"中,可以根据需要替换标题。def include_footer(the_links):    with open('templates/footer.html') as footf:        foot_text = footf.read()    link_string = ''    for key in the_links:        link_string += '<a href="' + the_links[key] + '">' + key + '</a>    '    footer = Template(foot_text)    return(footer.substitute(links=link_string))使用一个字符串作为参数,来创建一个HTML页面的尾部。页面本身存储在一个单独的文件"templates/footer.html"中,参数用于动态的创建一组HTML链接标记。从这些标记的使用来看,参数应当是一个字典。def start_form(the_url, form_type="POST"):    return('<form action="' + the_url + '" method="' + form_type + '">')这个函数返回表单最前面的HTML,允许调用者指定URl(表单数据将发送到这个URL),还可以指定所要使用的方法。    return('<p></p><input type=submit value="' + submit_msg + '"></form>')这个函数返回表单末尾的HTML标记,同时还允许调用者定制表单"submit"(提交)按钮的文本。def radio_button(rb_name, rb_value):    return('<input type="radio" name="' + rb_name +                             '" value="' + rb_value + '"> ' + rb_value + '<br />')给定一个单选钮名和值,创建一个HTML单选钮(通常包括在一个HTML表单中)def u_list(items):    u_string = '<ul>'    for item in items:        u_string += '<li>' + item + '</li>'    u_string += '</ul>'    return(u_string)给定一个项列表,这个函数会把该列表转换为一个HTML无序列表。一个简单的"for"循环就可以完成全部工作,每次迭代会向UL元素增加一个LI元素。def header(header_text, header_level=2):    return('<h' + str(header_level) + '>' + header_text +           '</h' + str(header_level) + '>')创建并返回一个HTML标题标记(H1、H2、H3等),默认为2级标题。"header_text"参数是必要的。def para(para_text):    return('<p>' + para_text + '</p>') </span></span>
<span style="font-size:18px;">用HTML段落标记包围一个文本段(一个字符串)。</span>
模块加载到IDLE,按下F5来执行。

默认的CGI响应首部的几种类型。

>>> start_response()'Content-type: text/html\n\n'>>> start_response("text/plain")'Content-type: text/plain\n\n'>>> start_response("application/json")'Content-type: application/json\n\n'
<span style="background-color: rgb(0, 153, 0);">include_header()函数生成Web页面的开始部分,允许定制页面的标题:</span>>>> include_header("Welcome to my home on the web!")'<html>\n<head>\n<title>Welcome to my home on the web!</title>\n<link type="text/css" rel="stylesheet" href="/coach.css" />\n</head>\n<body>\n<h1>Welcome to my home on the web!</h1>\n'
<span style="background-color: rgb(0, 153, 0);">include_footer()函数会生成一个Web页面末尾的HTML,并提供链接。第二个没有包含链接。</span>>>> include_footer({'Home':'/index.html','Select':'/cgi-bin/select/py'})'<p>\n<a href="/cgi-bin/select/py">Select</a>    <a href="/index.html">Home</a>    \n</p>\n</body>\n</html>\n'>>> include_footer({})'<p>\n\n</p>\n</body>\n</html>\n'
<span style="background-color: rgb(0, 153, 0);">start_form()和end_form()会建立一个HTML表单,并用参数来调整所生产的HTML的内容</span>>>> start_form("/cgi-bin/process-athlete.py")'<form action="/cgi-bin/process-athlete.py" method="POST">'>>> end_form()'<p></p><input type=submit value="Submit"></form>'>>> end_form("Click to Confirm Your Order")'<p></p><input type=submit value="Click to Confirm Your Order"></form>'
<span style="background-color: rgb(0, 153, 0);">radio_button()函数创建单选钮。</span>>>> for fab in ['John','Paul','George','Ringo']:radio_button(fab,fab)'<input type="radio" name="John" value="John"> John<br />''<input type="radio" name="Paul" value="Paul"> Paul<br />''<input type="radio" name="George" value="George"> George<br />''<input type="radio" name="Ringo" value="Ringo"> Ringo<br />'
<span style="background-color: rgb(0, 153, 0);">u_list()函数创建无序列表。</span>>>> u_list(['Life of Brian','Holy Grail'])'<ul><li>Life of Brian</li><li>Holy Grail</li></ul>'
<span style="background-color: rgb(0, 153, 0);">header()允许快速建立选定级别的HTML标题(默认级别为2)</span>>>> header("Welcome to my home on the web")'<h2>Welcome to my home on the web</h2>'>>> header("This is a sub-sub-sub-sub heading",5)'<h5>This is a sub-sub-sub-sub heading</h5>'
<span style="background-color: rgb(0, 153, 0);">para()把一个文本块包围在HTML段落标记中间</span>>>> para("Was it worth the wait?We hope it was...")'<p>Was it worth the wait?We hope it was...</p>'
控制你的代码

合理安排Web应用的目录结构,保证它有条理有组织。

CGI让Web服务器运行程序

Python提供的Web服务器

from http.server import HTTPServer, CGIHTTPRequestHandlerport = 8080httpd = HTTPServer(('', port), CGIHTTPRequestHandler)print("Starting simple_httpd on port: " + str(httpd.server_port))httpd.serve_forever()
显示选手列表

创建generate_list.py程序。

<span style="font-size:18px;">import athletemodelimport yateimport glob  #利用”glob“模块可以向操作系统查询一个文件名列表data_files=glob.glob("data/*.txt")athletes=athletemodel.put_to_store(data_files)</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">print(yate.start_response())print(yate.include_header("Coach Kelly's List of Athletes"))print(yate.start_form("generate_timing_data.py"))print(yate.para("Select an athlete from the list to work with: "))</span></span>
<span style="font-size:18px;"><span style="font-size:18px;">for each_athlete in athletes:    print(yate.radio_button("which_athlete",athletes[each_athlete].name))print(yate.end_form("Select"))print(yate.include_footer({"Home" : "/index.html"}))</span>
启动一个Web服务器并运行。进入webapp文件夹打开一个终端窗口,启动Web服务器:



在Web浏览器使用Web地址:http://localhost:8080.

Web服务器开始工作,它会把它处理的所有Web请求记录下来(显示在屏幕上)。


正确的生成了Web页面。



而且Web服务器记录了Web请求要允许"generate_list.py"CGI脚本。



创建另一个CGI脚本

需要生成一个新HTML页面,包含所有选手的前3个时间

点击一个单选钮然后按“选择”按钮时,会有新的Web请求发送到服务器。Web请求会指定要执行的CGI脚本,还会提供表单的数据。Web服务器会把表单数据作为输入发送到这个CGI脚本。可以使用CGI模块来访问表单数据。

<span style="font-size:18px;">import cgiform_data=cgi.FieldStorage()athlete_name=form_data['which_athlete'].value</span>
编写generate_timing_data.pyCGI脚本代码。

<span style="font-size:18px;">import cgitbcgitb.enableimport cgiimport athletemodelimport yateathletes=athletemodel.get_from_store()form_data=cgi.FieldStorage()athlete_name=form_data['which_athlete'].valueprint(yate.start_response())print(yate.include_header("Coach Kelly's Timing Date"))print(yate.header("Athlete:"+athlete_name+",DOB:"+athletes[athlete_name].dob+"."))print(yate.para("The top times for this athlete are:"))print(yate.u_list(athletes[athlete_name].top3))print(yate.include_footer({"Home":"/index.html","Select another athlete":"generate_list.py"}))</span>

测试驱动





遇到一个TypeError异常。

在CGI脚本的最前面增加这两行代码,启动Python的CGI跟踪技术。

<span style="font-size:18px;">import cgitbcgitb.enable()</span>

在Web浏览器后退,再次按下“选择”按钮。



top3()未定义!!!

一个小改变会让一切大不同

AthleteList类的top3()方法被重新指定为一个类属性。

<span style="font-size:18px;">@property  #这个修饰符允许访问"top3()"返回的数据时把它看作是一个类属性。    def top3(self):        return(sorted(set([self.sanitize(t) for t in self]))[0:3])</span>
要把top3()方法看作是一个类属性,应当这样调用:

<span style="font-size:18px;">print(yate.u_list(athletes[athlete_name].top3))</span>
而不是

<span style="font-size:18px;">print(yate.u_list(athletes[athlete_name].top3()))</span>
<span style="font-size:18px;">测试驱动结果:<img src="data:image/png;base64,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" alt="" /></span>








0 0
原创粉丝点击