python Web 之基石

来源:互联网 发布:淘宝打不开怎么办 编辑:程序博客网 时间:2024/04/27 09:34

  • 一 CGI 编程之前缀篇
    • 1CGI 入门简介
    • 2Apache2 的安装以及配置运行环境搭建
  • 二 开始 CGI programming 之旅
    • HTTP相关知识讲述 - - - first
    • demo 随后 - - - - second

一 、CGI 编程之前缀篇

1、CGI 入门简介

CGI:是通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。组成CGI通信系统的是两部分:一部分是html页面,就是在用户端浏览器上显示的页面。另一部分则是运行在服务器上的CGI程序。

首先,我们应该明确的是CGI只是一种接口模式,是现代的web开发的基础,这里的CGI程序可以是Python脚本,PERL脚本,SHELL脚本,C或者C++程序等。本篇文章会涉及到一些web后端处理程序(python3编写),一小部分前端H5部分,以及apache2 服务器的初级使用教程(涵盖基础配置,设置等)。

这里附上一张运行示意图:(如下)

原理图

2、Apache2 的安装以及配置(运行环境搭建)

注释:这里笔者用的是Ubuntu 16.04 + python3.5 +mysql数据库 运行环境

  • sudo apt-get install apache2
  • 检查是否成功
    • systemctl status apache2
    • 第二步,打开你的浏览器,在导航栏里输入 localhost 回车
    • 此时,出现Apache2 在Ubuntu 的导航网页,说明初步成功
  • 接下来,开始配置Apache2 的 CGI 编程环境,这里先讲述一下,默认安装后,有这几个目录需要注意一下。/etc/apache2 , /var/www/html ,/var/log/apache2/error(日志文件,经常用)

    • 为了我们方便编程,于是将编辑目录放在自己的用户目录,不用每次访问编写时,都需要sudo提高权限
    • apache2在/etc/apache2和/etc/apache2/sites-available两个文件夹下面分别有apache2.conf和000-default.conf两个配置文件需要改。然后,在自己的用户目录 mkdir -p www/html 和 mkdir -p www/cgi-bin 以后,html 和CGI都放置在相应得目录里面即可。

      • 编辑/etc/apache2/apache2.conf这个文件,找到<DDirectory /var/www/>这个选项,把其中的/var/www/修改为/home/chen/www注意这里的chen是笔者的用户目录,改成自己的用户目录。(原来的配置删掉或注释)

        -这里是我的一些配置

<Directory /home/chen/www/>    Options Indexes FollowSymLinks ExecCGI    AllowOverride All     Order allow,deny    Allow from all    AddHandler cgi-script .cgi .pl .py     Require all granted    </Directory>    少的东西自行添加
     - 编辑/etc/apache2/sites-available/000-default.conf这个文件,找到"DocumentRoot /var/www/html" 这个选项,把其中的/var/www/html修改为`/home/chen/www/html`。     - 使用命令`sudo /etc/init.d/apache2 restart`来重启**apache**服务。     - 在浏览器地址栏输入服务器地址,此时显示的是自定义目录下的文件(/home/chen/www/html ) 。     - 接下来配置CGI 相关         -  在`/etc/apache2/apache2.conf`文件中最后添加如下一行:         - `ScriptAlias /cgi-bin/ /home/chen/www/cgi-bin/`         - 这一行的意思是告诉Apache:任何以/cgi-bin/开头的资源都将映射到/home/chen/www/cgi-bin/目录中,且视之为CGI程序。         -  导入cgid包   ,接着在刚才文件最后加入 `LoadModule cgid_module /usr/lib/apache2/modules/mod_cgid.so` - 接下来就可以测试一下,是否配置好了 - 在自定义的/cgi-bin/文件夹中创建一个测试文件simple1.py 
#!/usr/bin/pythonprint 'Content-Type: text/html'print ''print '<html>'print '<h2>CGI Script Output</h2>'print '<p>This page was generated by a Python CGI script.</p>'print '</html>
 - 用命令chmod 755 simple1.py赋予文件执行权限浏览器地址栏中输入地址:`http://localhost/cgi-bin/simple1.py` - 如果有如下输出,这说明安装成功了 ![first CGI ](http://img.blog.csdn.net/20171201170430640?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc21pbGVqaWFzbWlsZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

注:安装过程如果出现错误,实在不能解决,可重新安装Apache 恢复默认,这里附上,完全卸载的方法 Apache 完全卸载

二 、开始 CGI programming 之旅

注:以下的 CGI 程序运行时,都需要使用chmod 755 EXE 提高执行权限,才可以运行,下面就不在重复讲述了

1 、HTTP相关知识讲述 - - - first

  • HTTP头部的格式如下:
HTTP 字段名: 字段内容

例如:
Content-type: text/html 即为HTTP头部的一部分,它告诉浏览器文件的内容类型是html格式。
- CGI程序HTTP头部常用信息:

这里写图片描述

  • CGI 的相关环境变量 — 通过环境变量进行相互通信

    这里写图片描述
    这里写图片描述

  • GET和POST方法
    浏览器客户端通过两种方法向服务器传递信息,这两种方法就是 GET 方法和 POST 方法。将在后面结合代码讲解。

2 、demo 随后 - - - - second

  1. 输出Apache 相关的运行信息 ,建立 environment.py 文件
#!/usr/bin/python3import codecs,sysimport ossys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)print ("Content-type: text/html")print ()print ("<meta charset=\"utf-8\">")print ("<b>环境变量</b><br>")print ("<ul>")for key in os.environ.keys():        print ("<li><span style='color:green'>%30s </span> : %s </li>" % (key,os.environ[key]))        print ("</ul>")

前三句代码主要是为了防止中文乱码,chmod 755 ,在导航栏输入localhost/cgi-bin/environment.py 即可运行

2、- 使用GET方法传输数据
GET方法发送编码后的用户信息到服务端,数据信息包含在请求页面的URL上,以”?”号分割, 如下所示:
http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2 有关 GET 请求的其他一些注释:
- GET 请求可被缓存
- GET 请求可被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET请求有长度限制 GET 请求只应当用于取回数据

  • 简单的url实例:GET方法
    以下是一个简单的URL,使用GET方法向hello_get.py程序发送两个参数:
    /cgi-bin/test.py?name=chen&url=http://Mr.chen’s site
#!/usr/bin/python3                                               import codecs ,sys sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)# CGI处理模块import cgi, cgitb # 创建 FieldStorage 的实例化form = cgi.FieldStorage() # 获取数据site_name = form.getvalue('name')site_url  = form.getvalue('url')print ("Content-type:text/html")print ()print ("<html>")print ("<head>")print ("<meta charset=\"utf-8\">")print ("<title>The site of Mr.chen </title>")print ("</head>")print ("<meta charset=\"utf-8\">")print ("<title> Mr.chen </title>")print ("</head>")print ("<body>")print ("<h2>%s官网:%s</h2>" % (site_name, site_url))print ("</body>")print ("</html>")      

浏览器输入localhost/cgi-bin/test.py?name=chen&url=http://Mr.chen's site 访问

3 、简单的表单实例:GET方法,以下是一个通过HTML的表单使用GET方法向服务器发送两个数据,提交的服务器脚本同样是hello_get.py文件,H5代码如下:

<!DOCTYPE html>                                                  <html>    <head>        <meta charset="utf-8">        <title> Mr.chen site</title>    </head>    <body>        <form action="/cgi-bin/hello-get.py" method="get">            this  is  www.futhureme.cn.  Welcome   Mr.chen   arrived ! ha ha  <br />              站点名称: <input type="text" name="name">  <br />            站点 URL: <input type="text" name="url" />            <input type="submit" value="提交 after sure" />        </form>    </body></html>

浏览器输入localhost/hello-get.html 访问

4 、使用POST方法传递数据,使用POST方法向服务器传递数据是更安全可靠的,像一些敏感信息如用户密码等需要使用POST传输数据。

以下同样是hello_get.py ,它也可以处理浏览器提交的POST表单数据:

#!/usr/bin/python3                                               import codecs ,sys sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)# CGI处理模块import cgi, cgitb # 创建 FieldStorage 的实例化form = cgi.FieldStorage() # 获取数据site_name = form.getvalue('name')site_url  = form.getvalue('url')print ("Content-type:text/html")print ()print ("<html>")print ("<head>")print ("<meta charset=\"utf-8\">")print ("<title> Mr.chen </title>")print ("</head>")print ("<body>")print ("<h2>%s官网:%s</h2>" % (site_name, site_url))print ("</body>")print ("</html>")  

表单通过POST方法(method=”post”)向服务器脚本 hello_get.py 提交数据,将上述的 html 中的 改为 method=”post” 即可。

5 、通过CGI程序传递checkbox数据
checkbox用于提交一个或者多个选项数据,HTML代码如下

<!DOCTYPE><html>    <head>        <meta charset="utf-8">        <title> Mr.chen(www.Mr_chen.cn) </title>    </head>    <body>        <form action = "/cgi-bin/checkbox.py" method = "POST" target = "_blank">            <input type = "checkbox" name = "http://blog.csdn.net/smilejiasmile" value = "on" /> The site of Mr.smile            <input type = "checkbox" name = "google" value = "on" /> Google     <br /> <br />            <input type = "submit" value = "选择站点" />        </form>    </body></html>

checkbox.py 文件的代码为:

#!/usr/bin/python3 # 引入 CGI 处理模块import cgi,cgitb# 创建 FieldStorageform = cgi.FieldStorage()# 接收字段数据if form.getvalue('google'):    google_flag = 'yes'else:    google_flag = 'No'if form.getvalue('http://blog.csdn.net/smilejiasmile'):    smile_flag = 'yes'else:    smile_flag = 'No'print ('Content-type:text/html')print ()print ('<html>')print ('<head>')print ('<meta charset = \'utf-8\'>')print ('<title> Mr.chen\'s site </title>')print ('</head>')print ('<body>')print ('<h2> Mr.chen\'s site is choised : %s </h2>'%smile_flag)print ('<h2> Google is choised : %s </h2>' %google_flag)print ('</body>')print ('</html>')

改权限 755 ,浏览器输入`localhost/checkbox.html

6 、通过CGI程序传递 Textarea 数据
Textarea 向服务器传递多行数据,HTML代码如下:

<!DOCTYPE><html>    <head>        <meta charset = "utf-8">        <title> Mr.chen's site </title>    </head>    <body>        <form action = "/cgi-bin/textarea.py" method = "post"target ="_parent">            please enter you content - - - - <br /><textarea name = "textcontent" cols = "80" rows = "6"></textarea>     <br /><br />            <input type = "submit" value = "click after suring" />        </form>    </body></html>

textarea.py 脚本代码

#!/usr/bin/python3 import codecs ,syssys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)# 引入 CGI 处理模块import cgi,cgitb# 创建 FieldStorage 的实例form = cgi.FieldStorage()# 接收字段数据if form.getvalue('textcontent'):    text_content = form.getvalue('textcontent')else:    text_content = 'nothing'print ('Content-type:text/html')print ()print ('<html>')print ('<head>')print ("<meta charset = \'utf-8\'>")print ('<title> The site of Mr.chen </title>')print ('</head>')print ('<body>')print ('<h2> you input content is :<pre>    %s </h2>'% text_content)print ('</body>')print ('</html>')

7 、通过CGI程序传递下拉数据框。
HTML 下拉框代码:

<!DOCTYPE html><html>    <head>        <meta charset = "utf-8">        <title> The site of Mr.chen </title>    </head>    <body>        <form action = "/cgi-bin/dropdown.py"  method = "post" target = "_parent">            <select name = "dropdown">                <option value = "Mr.chen's site" selected> chen </option>                <option value = "Google"> Google </option>            </select>        <input type = "submit" value = "click after suring" />        </form>    </body></html>

dropdown.py 脚本代码:

#!/usr/bin/python3 # 引入 CGI 处理模块import cgi,cgitb# 创建 FieldStrorage 的实例form = cgi.FieldStorage()# 接受字段数据if form.getvalue('dropdown'):    dropdown_value = form.getvalue('dropdown')else:    dropdown_value = 'Nothing'print ("Content-type:text/html")print ()print ('<html>')print ('<meta charset = \'utf-8\'>')print ('<title> The site of Mr.chen </title>')print ('</head>')print ('<body>')print ('<h2> your choise is : %s </h2>' % dropdown_value)print ('</body>')print ('</html>')

8 、CGI中使用Cookie , cookie 就是在客户访问脚本的同时,通过客户的浏览器,在客户硬盘上写入纪录数据 ,当下次客户访问脚本时取回数据信息,从而达到身份判别的功能,cookie 常用在身份校验中。

  • cookie的语法
    http cookie的发送是通过http头部来实现的,他早于文件的传递,头部set-cookie的语法如下:
Set-cookie:name=name;expires=date;path=path;domain=domain;secure 
  • name=name: 需要设置cookie的值(name不能使用”;”和”,”号),有多个name值时用 “;” 分隔,例如:name1=name1;name2=name2;name3=name3。
  • expires=date: cookie的有效期限,格式: expires=”Wdy,DD-Mon-YYYY HH:MM:SS”
  • path=path: 设置cookie支持的路径,如果path是一个路径,则cookie对这个目录下的所有文件及子目录生效,例如: path=”/cgi-bin/”,如果path是一个文件,则cookie指对这个文件生效,例如:path=”/cgi-bin/cookie.cgi”。
  • domain=domain: 对cookie生效的域名,例如:domain=”www.runoob.com”
    secure: 如果给出此标志,表示cookie只能通过SSL协议的https服务器来传递。
    -cookie的接收是通过设置环境变量HTTP_COOKIE来实现的,CGI程序可以通过检索该变量获取cookie信息。

9 、Cookie设置
Cookie的设置非常简单,cookie会在http头部单独发送。以下实例在cookie中设置了name 和 expires:

注意这儿的时间设置,不要让cookie过时了就行。

#!/usr/bin/python3 print ('Content-type:text/html')print ("Set-Cookie: name = 'Mr.chen';expires = Wed,1 Dec 2017 18:30:00 GMT")print ()print ("""<html>    <head>        <meta charset = "utf-8">        <title> The site of Mr.chen </title>    </head>        <body>            <h1> Cookie set OK ! </h1>        </body></html>""")

修改权限 755 ,浏览器运行即可完成设置cookie

以上实例使用了 Set-Cookie 头信息来设置Cookie信息,可选项中设置了Cookie的其他属性,如过期时间Expires,域名Domain,路径Path。这些信息设置在 “Content-type:text/html”之前。

10 、检索Cookie信息
Cookie信息检索页非常简单,Cookie信息存储在CGI的环境变量HTTP_COOKIE中,存储格式如下:
key1=value1;key2=value2;key3=value3….

demo 如下:

#!/usr/bin/python3 import codecs ,syssys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)# 导入模块import osfrom http import cookiesprint ("Content-type: text/html")print ()print ("""<html>    <head>        <meta charset = "utf-8">        <title> The sie of chen </title>    </head>    <body>        <h1> reading cookie 信息 </h1>""")if 'HTTP_COOKIE' in os.environ:    cookie_string = os.environ.get('HTTP_COOKIE')    c = cookies.SimpleCookie()    c.load(cookie_string)    try:        # 捕捉异常        data = c['name'].value        print ("<h2> cookie data: "+ data + "</h2> <br>")    except KeyError:        print ("cookie 没有设置或者已经过时 <br>")print ("""    </body>    </html>    """)

修改权限 755 ,浏览器运行即可完成获取 。

11 、文件上传实例
HTML设置上传文件的表单需要设置 enctype 属性为 multipart/form-data,代码如下所示:

<!DOCTYPE><html>    <head>        <meta charset = "utf-8">        <title> The site of Mr.chen </title>    </head>    <body>        <meta charset = "utf-8">        <form enctype = "multipart/form-data"            action = "/cgi-bin/save_file.py" method = "post">            <p> 选中文件:            <imput type = "file" name = "filename" id = "file" class = "inputfile"/>            <imput type = "file" name = "filename" id = "file" class = "inputfile"/>  </p>            <p><input type = "submit" value = "upload" /></p>        </form>    </body></html>

save_file.py脚本文件代码:

#!/usr/bin/python3 import cgi,osimport cgitb;cgitb.enable()form = cgi.FieldStorage()# 获取文件名 fileitem = form['filename']# 检测文件是否上传if fileitem.filename:    # 设置文件路径    fn = os.path.basename(filename)    open('/tmp/'+fn,'wb').write(fileitem.file.read())    message = '文件 "' + fn + '" upload success'else:    message = 'no file upload'print("""\        Content-Type:text/html\n        <html>        <head>        <meta charset= 'utf-8'>        <title> The site of Mr.chen </title>        </head>        <body>            <p>%s </p>        </body>        </html>        """%(message,))

修改权限 755 ,浏览器运行即可。

12 、文件下载对话框
我们先在当前目录下创建 foo.txt 文件,用于程序的下载。
文件下载通过设置HTTP头信息来实现,功能代码如下:

#!/usr/bin/python3# HTTP 头部print ("Content-Disposition:attachment;filename = \"foo.txt\"")print ()#打开文件fo = open("foo.txt","rb")str = fo.read();print(str)# 关闭文件fo.close()

注: 本文参考,自己的学习笔记,以及一些网站,如,runoob 等,整合而成。
—- Mr.chen