在学习python的web开发时,首先使用了python3中内建的HTTP servers。
使用如下代码:
from http.server import HTTPServer, CGIHTTPRequestHandler
port = 8080
httpd = HTTPServer(('', port), CGIHTTPRequestHandler)
print("Starting simple_httpd on port: " + str(httpd.server_port))
httpd.serve_forever()
创建一个web服务器文件simple_httpd.py,在终端上运行该文件:
在浏览器的地址栏输入 http://localhost:8080,可打文件simplehttpd.py所在文件夹里的index.html页面。
这样就可以对index.html作个性化设计,来实际操练基于python的CGI脚本的web开发了。
背景:一个教练带着一群跑步运动员训练,并为每一个选手每一次测试时间进行记录,教练想要一种很方便的方式来管理这些测试数据,譬如需要查看每个选手跑得最快的3次记录,查看指定选手的所有测试记录,为选手添加新的记录等功能。
方案:为教练设计一个webapp,该web应用遵循MVC模式。
我们将顶层文件夹命名为mrdw,
下面包含cgi-bin、data、images、templates等子文件夹,还包括index.html、CSS样式表等不适合放在前面子文件夹中的其他文件。
特别命名的cgi-bin文件夹用来放为web应用所写的代码文件;
data文件夹用来放测试的数据文件;
images文件夹用来放web应用相关的图片文件;
templates文件夹用来HTML网页模板。
为了支持更多更灵活的功能,需要使用database management system(数据库管理系统)来支持web应用的数据管理。我们采用轻量级的SQLite作为web应用的数据库,导入python的内建模块sqlite3后,就可以使用python的标准化数据库API来编程。
现在来实现为现有选手增加新的测试记录这一功能,
重写模板form.html文件和脚本test_form.py,效果如下:
在这个HTML表单里填入选手的id和新的时间数据,然后点击Send按钮就可以将数据发送到web server,并由指定脚本add_timing_data.py来处理,将新的数据存储到数据库文件coachdata.sqlite里。
为了确保存入数据里的数据的正确性,我们应该对发送过来的数据做有效性检查。
于是我们在athletemodel.py模块里面定义一个函数check_athleteId(athlete_id)来检查athlete_id是存在于数据库里。
第一个版本:
def check_athleteId(athlete_id):
connection = sqlite3.connect('coachdata.sqlite')
cursor = connection.cursor()
results = cursor.execute("""SELECT id FROM athletes""")
id_list = [row[0] for row in results.fetchall()]
connection.close()
print('id_list is ', id_list)
for each in id_list:
if each == athlete_id:
return (True)
else:
continue
return (False)
在server上被文件add_timing_data.py调用时执行出错:
但是在python3.4.2 解释器环境下运行正确:
然后第二个版本:
def check_athleteId(athlete_id):
connection = sqlite3.connect('coachdata.sqlite')
cursor = connection.cursor()
results = cursor.execute("""SELECT id FROM athletes""")
id_list = [row[0] for row in results.fetchall()]
connection.close()
print('id_list is ', id_list)
if athlete_id in id_list:
return (True)
else:
return (False)
还是出错:
同样在python3.4.2 解释器环境下运行正确:
再尝试第三个测试版本:
def check_athleteId(athlete_id):
connection = sqlite3.connect('coachdata.sqlite')
cursor = connection.cursor()
results = cursor.execute("""SELECT id FROM athletes""")
id_list = [row[0] for row in results.fetchall()]
connection.close()
print('id_list is ', id_list)
idx = id_list.index(athlete_id)
print(idx)
return (idx)
还是出错:
同样在python3.4.2 解释器环境下运行正确:
以上测试在32位的windows系统和ubuntu系统全都测试过,表现一样。
最后采用第四版,代码参见:https://github.com/robot527/python_primer/blob/master/mrdw/cgi-bin/athletemodel.py
终于达到了预想的效果。
后来与同事讨论后,发现了问题所在,
原因在于add_timing_data.py文件里,
new_data = {}
for key in form.keys():
new_data[key] = form[key].value
the_id = new_data['Athlete_id']
the_time = new_data['Time']
if check_athleteId(the_id):
处理后这个变量the_id是一个字符串,作为参数传入函数check_athleteId里,执行结果与预想的不一致,所以出现了上述所谓的错误!
所以使用前面三个版本的检查函数时,都应该将 if check_athleteId(the_id): 修改为 if check_athleteId(int(the_id)): 。
学习和实践过程中难免会碰到一些短时间难以解释的问题,这时就需要我们冷静,多思考各种细节问题,还要多动手尝试,相信最终总会找到解决问题提的办法的
Ps:那么新问题又来了,为什么第四版
def check_athleteId(athlete_id):
connection = sqlite3.connect(db_name)
cursor = connection.cursor()
results = cursor.execute("""SELECT name FROM athletes WHERE id = ?""", (athlete_id,))
sel_data = results.fetchall()
connection.close()
if sel_data == []:
return (False)
else:
return (True)
对于输入参数athlete_id为字符串或者整数时都可以正常工作?
版权声明:本文版权属于若要走,并受法律保护。
本文授权方式采用 Creative Commons「署名 - 非商业性使用 - 禁止演绎 4.0」许可协议。
接受自由转载,但必须署名、注明来源,且禁止用于商业用途。