4w作业

作业要求

本周整体任务概述:

  • 在上周开发基础上, 完成 极简交互式笔记的Web版本
  • 需求如下:
    • 通过网页访问系统:
    • 每次运行时合理的打印出过往的所有笔记
    • 一次接收输入一行笔记
    • 在服务端保存为文件
  • 同时兼容 3w 的 Net 版本的命令行界面进行交互

背景:

  • 系统:mac os 10.10
  • python:Python 2.7
  • 编辑器:vim
  • 终端:iTerm

安装bottle

官网 :http://bottlepy.org/docs/dev/tutorial.html

直接按照官网的下载

wget http://bottlepy.org/bottle.py

提示:

!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://github.com/defnull/bottle/raw/master/bottle.py">here</a>.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at bottlepy.org Port 80</address>
</body></html>

直接打开上面链接,跳转到另一个链接,用下面命令下载

curl -o bottle.py https://raw.githubusercontent.com/bottlepy/bottle/master/bottle.py

hello world开始

运行看看,找找感觉

from bottle import route, run

@route('/hello')
def hello():
    return "Hello World!"

run(host='localhost', port=8080, debug=True)
  • route():的函数是将一段代码绑定到URL上,上面的例子就是将hello()函数绑定到/hello 的URL上,也就是直接定义URL
  • host跟port绑定ip个端口
  • run() 启动服务
  • debug=True 开启开发模式。

在终端运行curl http://localhost:8080/hello 就看到hello world

添加动态URL

    from bottle import route, run

    @route('/hello/<custon_url>')
    def hello():
        return "Hello World! %d " custon_url

    run(host='localhost', port=8080, debug=True)

终端输入:

http://localhost:8080/hello/dd
Hello World! dd

给 /hello/自定义一个变量

如何进行POST请求

#/usr/bin/env python
from bottle import route, run,request,debug

@route('/table')
def table():
    return '''
        <html>
        <head>
        <body>
        <form action="/table" method="post">
        Name:<input name="name" type="text" />
        Gender:<input name="gender" type="text" />
        Age:<input name="age" type="text" />
        Weight:<input name="weight" type="text" />
        Height:<input name="height" type="text" />
        <input value="Table" type="submit" />
        </form>
        </body>
        </html>
'''

@route('/table', method='POST')
def for_table():
    name = request.forms.get('name')
    gender = request.forms.get('gender')
    age = request.forms.get('age')
    weight = request.forms.get('weight')
    height = request.forms.get('height')

    return '<p> Name:%s </p><p> Gender:%s </p><p> Age:%s </p><p> Weight:%s </p><p>Height:%s</p>' %(name, gender, age, weight, height)

run(host='0.0.0.0', port=8080, debug=True)

重点在于@route('/table', method='POST')

当访问table页面时,同时带上post的请求,request.forms.get 获取数据给予HTML读取。

查询搜索变量

@route('/search')
def search():
    search = request.query.search
    return 'search=%s' % (search)

curl http://0.0.0.0:8080/search?search=test

结果:

search=test

这里是request.query把URL获取的值,返回到网页中。

template模板使用

简单来说就是把上面的post的例子,里面的HTML代码分离出来,放到一个后缀为tpl的文件里。

建一个table.tpl文件

<html>
    <head>
    <body>
    <form action="/table" method="post">
    Name:<input name="name" type="text" />
    Gender:<input name="gender" type="text" />
    Age:<input name="age" type="text" />
    Weight:<input name="weight" type="text" />
    Height:<input name="height" type="text" />
    <input value="Table" type="submit" />
    </form>
    </body>
</html>

.py文件的内容

from bottle import route,run
from bottle import template

@route('/table')
def table():
    return template('table') #模板的名称

run(host='localhost', port=8080, debug=True)

如何把后端的数据传输给远端

.py文件内容

   from bottle import route,run
   from bottle import template
   @route('/table')
   def table():
      name = 'cxiaodian'
      return template('table', name = name)

   run(host='localhost', port=5000, debug=True)

.tpl文件内容

   <html>
   <body>
       <p>姓名: </p>
   </body>
   </html>

显示结果:

姓名: cxiaodian
在.tpl文件模板中,{{name}} 就是后端传过来的数据,return template('table', name = name) 后端return 过来的name 变量给予前端 name显示,模板中{{}}用来调用后端的数据

网页端如何读取本地数据

思考:

先从本地读取本地日记文件
再把读取的数据传送到网页端
本地需要提供一个能让网页端读取的接口

  • 读取本地日记文件

      def read_diary():
          txt = open('mydiary.txt', 'r')
          data = txt.readlines()
          diary_data = txt.read()
          txt.close()
          return diary_data
    

    上面的函数读取本地日记,diary_data给予读取的数据定义

       @route('/diary')
       def diary():
           data = read_diary()
           return template('table', data = data)
    

把读取的日记输出给予网页端,

<html>
<body>
<ul>
    <li>历史日记 : {{data}}</li>
</ul>
</body>
</html>

读取日记成功

思考:

如何把网页端写入的数据保存服务端,并把历史自己显示出来

添加一个写入函数:

def write_diary(writedata):
     write_txt =open('mydiary.txt', 'a+')
     write_txt.write('\n' + writedata)
     write_txt.close()

.tpl文件写入html

<html>
<form action="/diary" method="post">
<input name="input_data" type="text" />
<input value="写入"  type="submit">
</form>
<ul>
 % for line in data:
 {{line}}<br>
 % end
</html>

开始写的html总是不会换行显示,后面参考了 sunoonlee 同学的html模块,需要添加
才解决了这个问题。

  % for line in data:
     {{line}}<br>
     % end

input_data的数据传给后端,后端写入到本地mydiar.txt文件,再把read_diary()函数返回到给网页端显示。

@route('/diary', method='POST')
   def input_data():
      do_data = request.forms.get('input_data')
      write_diary(do_data)
      return template('table' data=read_diary())

网页端写入日记,并能显示出来。

  • 20151111 更新

如何从命令端读取网页端数据?

搜索python get url 找到urllib 能够打开URL读取内容,

看了下例子,稍微修改下url

import urllib

   response = urllib.urlopen('http://localhost:50007/diary')
   response = response.read()
   print response

确实是可以把网页端的数据读取出来,但是会把html代码跟输入框也读取出来。

想到能不能在server端单独给予clien端一个接口?

在server添加了一小段代码

@route('/read')
 def read_from_url():
     return read_diary()

clien端直接读取http://localhost:50007/read URL,能读取历史日记

如何从终端写入数据到网页端?

查阅了urlliburllib2 的例子中, 调用服务端后台给予网页端写入的接口,进行写入日记。

    def write_diary(diary):
            data = {}
            data['input_data'] = diary
            data = urllib.urlencode(data)
            urllib.urlopen('http://localhost:50007/diary')

再用1w的作业 while 循环判断。

服务端,跟客户端基本框架完成,20151112

还需要:

  • 调用 Jinja2模板
  • Bootstrap 框架
  • DB数据库

如何调用 Jinja2模板

读了jinja官网的帮助文档,看得不是很懂,琢磨了半天大概jinja2模板能跟bootstrap框架结合,让页面更好看把,搜索下Jinja2 templates and Bottle 按照里面的例子摸索下,大概知道jinja是怎么用,指定一个html文件。

@route('/diary')
@jinja2_view('home.html')

到bottstrap官网下载个模板,对html不是很懂,边查边修改,然后直接套用进去。

关于添加数据库

在python 帮助文档,琢磨半天,还是不太懂,后来直接看了下其他同学的代码, sunoonlee 才大概知道是怎么用,直接按照sunoonle的数据库代码修改,琢磨,测试(是不是很不厚道?),运行成功,也能理解怎么去调用了。

添加了数据库,代码改动很多,之前的clent端的代码需要重新修改。

感想

一步步从网页端读取后端的数据,大概了解,网页端与后端的数据是如何进行对接了,bottle调用jinja2模板,加强模板功能,jinja2直接调用bootstrap,减少开发前端的时间成本,就能起到美化网站,而数据库能更好的协助前后端数据的传输,与管理。

发觉有时看了官网一堆文字,都不知道怎么用,而如果直接拿起例子修改,调试,更容易理解。