Python 学习笔记5

来源:互联网 发布:超级基因优化液扫书 编辑:程序博客网 时间:2024/05/17 22:58

5、Python Web开发

1Web 开发介绍

1-1 Web 开发概述

C/S

 

B/S – web开发

 

访问网站的过程:

  静态网站

  动态网站 – 网站由于用户的请求不同,而呈现出不同的的结果

 

MVC

  M –Model模型,存储web应用数据的代码– user类的实现,对象

  V –View视图,格式化和显示web应用的用户界面的代码– 首页,视频

  C –Controller控制器,将Web应用粘合在一起并提供业务逻辑的代码– 联系M和V,用于登记,注册

 

CGI – Common Gateway Interface

  可以让一个客户端,从网页浏览器向服务器请求数据。这是描述客户端和服务器程序之间传输数据的一种标准。

 

1-2 Web 应用的结构

Web应用结构概览:

  前端程序 – HTML CSSJS

  后台程序 – pythonPHP JSP

  数据库 – MySQL MongoDB

 

前端

  HTML– 超文本标记语言

  CSS– 层叠样式表

  JS– JavaScript

 

后端- Python PHP JSP ASP/ASP.NET

 

数据库- MySQL MongoDB SQLite

 

1-3 HTML 和 JavaScript 的简单介绍

目标:实现两个数的加法

 

 


 

2 用 Python 进行 CGI 编程

2-1 CGI 介绍

CGI

  CGI是运行在服务器上的程序,提供同客户端HTML页面的接口。

  CommonGateway Interface

  CGI程序可以是PythonPerl C C++, 不限定语言

 

CGI的工作原理

  浏览器访问URL并连接到Web服务器

  Web服务器接收到请求信息后会解析URL,并查找访问的文件在服务器上是否存在,如果存在就返回文件内容,否则返回错误信息

  浏览器从服务器上接收信息,并显示接收的文件或错误信息

  其中有一些与数据库交互的工作

 

缺点与改进

  每次CGI请求都会生成一个程序的副本来运行

  FastCGI- 先编译

  mod_perl– 将解释器作为模块集成在web服务器中

  使用c等编译

 

CGI中环境变量

  CONTENT_TYPE:指示传递信息的类型

  HTTP_COOKIE:客户机的COOKIE内容

  REMOTE_ADDR:发送请求的客户机的IP地址

  REQUEST_METHOD:脚本被调用的方法,如GET和POST方法

 

GET方法

  GET方法发送用户信息到服务端,数据信息包含在请求URL上,以?分割

  GET请求可被浏览器缓存

  GET请求会保存在历史记录中

  GET请求有长度的限制

  GET请求不应用于敏感场合

  GET请求只应当用于取回数据

 

POST方法

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

 POST请求包含在HTTP请求的头

 POST请求不会显示在URL中

 

2-2 python中的web服务器

Python自带的web服务器 – Python自带的包可以建立简单的Web服务器

  BaseHTTPServer:提供的基本的web服务和处理类

SimpleHTTPServer: 包含执行GET请求的SimpleHTTPRequestHandler类

CGIHTTPServer: 包含处理POST请求和执行的CGIHTTPRequestHandler类

演示:python –m CGIHTTPServer 8081

 

使用Apache

 

第一个CGI程序

  创建目录

  编写CGI程序

  开启服务器

  使用浏览器访问

 

实例:实现简单的GET请求

import cgi,cgitb

 

form1 = cgi.FieldStorage()

 

name = form1.getvalue("name")

 

print "content-type:text/html \n\n"

print "Hello "+name

 

在命令行中,python –m CGIHTTPServer 8081

在浏览器中,http://localhost:8081/cgi-bin/main.py?name=yx

 

2-3 实战:用CGI编写加法器

目标:

    使用python, GETPOST请求,配合HTML和JS程序,完成之前的加法器。并开启服务器,使得其他人可以访问。

 

 


 

3Python Web 框架开发

3-1 Web 开发框架介绍

框架 – 最基础的软件构架和体系– 骨架

 

好处:

  可重用

  成熟,稳健

  可扩展性良好

  提高开发速度

 

Web框架

  Web应用框架是支持动态网站、网络应用程序的软件框架。

  Web框架的工作方式:接受HTTP请求并处理,分派代码,产生HTML,创建HTML响应。

  Web框架通常包含了:URL路由,数据库管理,模板引擎。

 

优点:

  着重业务逻辑

  高度可重用

  选对框架很重要

 

MVC

 

ORM – 将具体的类映射为一张表

 

URL Route – URL不同的地址映射到不同的函数中,来完成不同的操作

 

修饰器

 

Temple – 模板引擎 – 将后台的数据通过渲染的方式传递给前端代码

 

3-2 python中的web框架

常见的web框架:

  大包大揽的Django

  力求精简的web.py和Tornado

  新生代的微框架Flask和Bottle

 

Django的优点:

  完美的文档

  全套的解决方案(Cache,Session, ORM……)

  强大的URL路由配置

  自助管理后台

 

Django的缺点:

  系统紧耦合

  自带的ORM不够强大

  Template比较弱

 

微框架的优点:

  聚焦在业务逻辑上

  学习成本低

  灵活性和伸缩性较强

 

微框架的缺点:

  很多逻辑需要开发者操刀

  安装很多模块之后体积较大

 

Flask框架

  保持核心简单,易于扩展

  不包含数据库抽象层,表单验证等。但可以添加扩展。

  Flask是一个可扩展框架

 

安装Flask框架

在目录C:\Python27\Scripts中,pip install flask

 

检验:python

     Import flask

 

3-3 使用Flask框架编写加法器

目标:

   使用python,Flask框架,配合HTML和JS程序,完成之前的加法器。并开启服务器,使得其他人可以访问

 

在HTML文件中编写非HTML代码时,需要使用{{ }}

 

 


 

4Flask 表单开发

4-1 表单介绍

表单– html中的数据采集器

含义:可以采集到用户输入的内容

组成:标签、域、按钮

功能:通过表单,将用户输入的数据提交给服务端,并交由服务端进行处理

 

表单标签– 声明表单的范围,位于表单标签中的元素将被提交

  语法:<form></form>

  属性:Method –GET POST, Enctype, action…

 

表单域

  语法:<input……/>

  属性:type,name,value…

  种类:文本框<…type=text>

密码框<…type=password>

文本区域<textarea></textarea>

文件上传框<…type=file>

单选框<…type=radio>

复选框<…type=checkbox>

 

表单按钮

  提交按钮 <inputtype="submit" value="Submit">

  复位按钮 reset

  一般按钮 button

实例– 一个含有多种元素的表单

使用HTML语言,尝试编写一个含有多种元素的表单。并进行简单的排版,尝试通过JS取得页面元素的值

// index.html

<<!DOCTYPE html>

<html>

<head>

           <title></title>

           <scripttype="text/javascript" src="getValue.js"></script>

</head>

 

<body>

           <formname="form1">

                     <inputtype="text" placeholder="Text" name='text1' />

                     <inputtype="password" placeholder="password"name="password"/>

                     <textareaplaceholder="Textarea" name="textarea"style="resize:none"></textarea>

                     <inputtype="file" name="file"/>

                     <inputtype="radio" name="option"value="option1"/>Option1

                     <inputtype="radio" name="option"value="option2"/>Option2

                     <inputtype="checkbox" name="check"value="Option1"/>Option1

                     <inputtype="checkbox" name="check"value="Option2"/>Option2

 

                     <inputtype="submit" value="Submit"/>

                     <inputtype="reset" value="Reset"/>

                     <inputtype="button" value="button"onclick="getValue()">

           </form>

</body>

</html>

 

 

function getValue () {

           vartext = document.form1.option.value; //单选框返回的是一个元素

           alert(text)

           //body...

}

 

 

function getValue () {

           var arr = document.form1.check; //复选框返回的是一个数组

           alert(arr[0].value);

           // body...

}

 

 

4-2 表单的提交方式

get 和 post

  GET方式通过URL提交数据,数据在URL中可以看到的

  POST方式,数据放置在HTML Header中提交

  例如:GET 方式:https://www.baidu.com/s?wd=yuxiang

       POST方式:在HTTP头中提交wd=yuxiang

 

两者区别:

GET请求可以被浏览器缓存

POST所请求的URL可以被缓存,但数据不会缓存

POST请求不便于分享

POST请求没有长度限制

GET请求的数据暴露在URL中,会带来安全问题

 

GET方式的适用场合

  单纯的请求数据,不进行其他操作

  表单数据较短,不超过1024个字符

  对安全性要求一般的场合

 

POST方式的适用场合

  数据不仅仅用于请求,例如,需要将数据插入数据库內

  表单数据过长,如,博客

  要传的数据不是ASCII编码

 

4-3 实战:用Flask开发用户管理(一)

目标:使用Flask框架,配合HTML和JS程序,编写一个页面,判断用户提交的用户名和密码是否分别为yx和35,如果是则调整到极客学院的首页,否则返回错误信息

 

  //使用request.form从表单中拿用户输入的数据

  username= request.form[‘username’]

 password = request.form[‘password’]

 

  //给用户提示输入登录信息错误

 //index.html

{% if message %} {{ message }} {% endif %}

在模板引擎中,用{%…%}来控制流

 

//当数据量较大时,使用Flask-wtf构建表单

pip install Flask-wtf

# 在视图函数中得到表单的内容

  myForm.username.data== "yx" and myForm.password.data == "35" andmyForm.validate()

 

 

代码一:

#main.py

# coding=utf-8

from flask import Flask, request,render_template, redirect, url_for

 

from wtforms importForm,TextField,PasswordField,validators

 

class LoginForm(Form):

           username= TextField('username',[validators.Required()])#[validators.Required()]表示username必须填入

           password= PasswordField('password',[validators.Required()])

 

app=Flask(__name__)

 

@app.route('/',methods = ['GET','POST'])

def index():

           returnredirect(url_for("login"))

 

@app.route("/user",methods=['GET','POST'])

def login():

           myForm= LoginForm(request.form)

           ifrequest.method=='POST':

                     ifmyForm.username.data == "yx" and myForm.password.data =="35" and myForm.validate(): # 在视图函数中得到表单的内容

                                returnredirect('http://www.jikexueyuan.com')

                     else:

                                message = "LoginFailed"

                                returnrender_template('index.html',msg=message,fm=myForm) # msg给用户提示输入登录信息错误,fm创建表单

           returnrender_template('index.html',fm=myForm)

 

if __name__ == "__main__":

           app.run(port=8080)

 

代码二:

#index.html

<body>

           <divalign="center">

           <h1>UserManmgement</h1>

                     <formmethod="POST">

                                {%if msg %} {{ msg }} {% endif %} //错误提示信息位置

                                <br/>

                                Username:{{fm.username}}//创建用户名表单

                                <br/>

                                Password:{{fm.password}}//创建密码输入表单

                                <br/>

                                <inputtype="submit" value="Submit"/>

                                <inputtype="reset" value="reset"/>

                     </form>

           </div>

</body>

 

 


 

5Python 的数据库连接

5-1 数据库基础

数据库

 

数据库管理系统

 

数据库分类

  关系型数据库:MySQL SQLite PostgreSQL Oracle Access…

  非关系型数据库:BigTableMongoDB LevelDB …

 

为什么使用DBMS?

  减少记录编档的时间

  减少记录检索的时间

  灵活的查找序列

  灵活的输出格式

  多个用户同时访问记录

 

安装MySQL数据库和相关管理工具

  MySQL

 WorkBench – 图形化管理界面

 

5-2 数据库查询语句SQL

SQL

 

实例

insert into student (id,name) values(1,'yx') ;

delete from student where id = 2;

update student set name="yuxiang"where id=1;

select * from student where id = 1;

select * from student order by id desc; //降序

select * from student order by id asc; //升序

 

 

5-3 在python中进行SQL操作

目标:

  1)编写一个Python程序,重复第二课时中数据库操作

  2)编写一个Python程序,允许用户输入的内容存储在数据库中

 

找到C:\Program Files\MySQL\MySQL Server 5.7\bin

在命令行窗口输入:mysql.exe -u root -p,回车后输入mysql的密码,即可进入mysql中

pip install mysql-python

python

import MySQLdb

 

注:在ubuntu中,建议用apt-get安装

sudo apt-get install python-mysqldb

 

在Workbench中,勾上表的Auto Increment,表明这个字段是自增的

 

#! coding=utf-8

import MySQLdb

 

#connect to db

conn = MySQLdb.connect("localhost","root","root","test")

 

#create cursor

cur = conn.cursor()

name = raw_input()

 

#sql

sql = "select * from student"

insert_sql = "insert into student(name) values ('%s')" %(name)

 

#execute

cur.execute(insert_sql)

conn.commit()#防止数据不一致

 

cur.execute(sql)

 

#get the result

result = cur.fetchall()

 

for row in result:

   print row[0]

   print row[1]

 

conn.close()

 

 

5-4 实战:使用Flask框架编写用户管理(二)

目标:

使用Flask框架,配合HTML和JavaScript程序,编写两个页面。第一个页面允许用户填入用户名和密码进行注册,第二个页面用户使用刚才的用户名和密码进行登录。

 

代码:

# db.py

# execute datebase operation

 

import MySQLdb

 

conn=MySQLdb.connect("localhost","root","root","test")

 

cur = conn.cursor()

 

def addUser(username,password): #向数据库中插入用户名和密码,用户注册

           sql= "insert into user (username,password) values ('%s','%s')" %(username,password)

           cur.execute(sql)

           conn.commit()

           conn.close()

 

def isExisted(username,password): #查询数据,用户登录

           sql= "select * from user where username = '%s' and password = '%s'"%(username,password)

           cur.execute(sql)

           result= cur.fetchall()

           if(len(result) == 0):

                     returnFalse

           else:

                     returnTrue

 


 

6 数据库进阶-对象关系映射(ORM)的使用

6-1 对象关系映射 (ORM) 介绍

ORM – 用于实现面向对象程序设计里的不同类型之间系统的数据之间的转换

不同类型之间系统– 面向对象程序(软件工程)和关系型数据库(数据理论)之间数据

 

为什么要使用ORM

  避免和复杂的SQL语句打交道

  提高开发效率,也更容易理解

  方便形成统一风格的代码

  带来一些安全性上的提升

 

ORM缺点:

  系统消耗较大

  处理较复杂的查询条件时,使用ORM不够灵活

  占用内存较大

 

Flask中的ORM

  Flask-SQLAlchemy:基于SQLAlchemy的Flask扩展

  peewee,pyORM

 

6-2 实战:使用ORM编写用户管理模块(三)

目标

1)  安装配置Flask-SQLAlchemy

2)  在之前用户管理模块的基础上,为用户建立数据模型,通过此模型完成用户的登录、注册等操作

安装:

  pip install flask-sqlalchemy

验证:

  python

  from flask.ext.sqlalchemy import SQLAlchemy

 

代码一:

#model.py

from flask import Flask

from flask.ext.sqlalchemy import SQLAlchemy

 

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] ='mysql://root:root@localhost/test'

db = SQLAlchemy(app)

 

class User(db.Model):    //创建表

           id= db.Column(db.Integer,primary_key=True)

           username= db.Column(db.String(32),unique=True)

           password= db.Column(db.String(32))

           def__init__(self,username,password):

                     self.username= username

                     self.password= password

在命令行中测试:

  进入python

  >>>frommodel import *

 >>>db

 >>> db.create_all()  //创建表

  到workbench中查找user表

 

代码二:

           defadd(self):  //数据库插入,用户注册

                     try:

                                db.session.add(self)

                                db.session.commit()

                                returnself.id

                     exceptException,e:

                                db.session.rollback()

                                returne

                     finally:

                                return0

 

代码三:

//数据库查询,用户登录

           defisExisted(self):

                     temUser= User.query.filter_by(username=self.username,password=self.password).first()

                     iftemUser is None:

                                return0

                     else:

                                return1

 

6-3 实战:使用ORM编写留言板(一)

目标

1)  使用Flask框架以及Flask-SQLAlchemy扩展,建立留言的模型,并通过此模型,完成一个允许用户留言的程序

2)  用户可以输入用户名以及留言内容,发布留言。并将所有用户的留言显示在一个页面中

代码一:

#model.py

class Entry(db.Model):

           id= db.Column(db.Integer,primary_key=True)

           content= db.Column(db.Text)

           sender= db.Column(db.String(32))

           def__init__(self,content,sender):

                     self.content= content

                     self.sender= sender

           defadd(self):   #数据库插入,用户将留言板的数据插入

                     try:

                                db.session.add(self)

                                db.session.commit()

                                returnself.id

                     exceptException,e:

                                db.session.rollback()

                                returne

                     finally:

                                return0

def getAllEntry():  #ORM查询操作,简化,从数据库中拿出用户输入的内容

           Entlist= []

           Entlist= Entry.query.filter_by().all()

           returnEntlist

 

#main.py中调用

e =Entry(myEntryForm.content.data,myEntryForm.sender.data)

e.add()

 

#main.py中调用

l = getAllEntry()

 

代码二:

class PublishForm(Form): // 从表单中拿出用户输入的数据

           content= TextField('content',[validators.Required()])

           sender= TextField('sender',[validators.Required()])

 

<body>

           <formmethod="post">

                     content:{{fm.content}}  //创建表单,用户从此处输入数据

               </br></br>

               sender: {{fm.sender}}

               <input type="Submit"value="Submit"> Submit

               <br>

               <input type="reset"value="Reset"> Reset                    

           </form>

           <ul>

                     {%for e in entries %}

                     <li>{{e.content }} Send by {{ e.sender}}  //在留言板中输入数据库中的内容

                     {%endfor %}

           </ul>

</body>


 

7 数据库中的关系

7-1 数据库中的关系概览

关系型数据库就是建立在关系模型基础上的数据库,借助于集合代数等数学上的概念和方法来处理数据库中的数据。

 

关系模块中的常用的操作有数据查询(如选择,投影,连接,并,交等)和数据操作(增删改查)

 

表示以行和列组织起来的数据的集合。一个数据库包括一个或多个表。在关系型数据库中,

一个表就是一个关系,一个关系数据库可以包括多个表。

 

关系的种类:一对一,一对多,多对多

 

7-2 关系的设计

主键:

  数据表中某一记录有若干条属性,若某一属性可以唯一标识一条记录,该属性就可以成为一个主键。

 

外键:

是用于与另一张表的关联,是能确定另一张表记录的字段,用于保持数据的一致性。

 

主键要能够被外键有效的引用。

 

演示:数据表的设计

目标:使用SQL语句和MySQL WorkBench,完成一个可以在数据库中找到特定用户文章的小程序。

 

一对一:

表region

id

name

team_id

1

beijing

2

2

shenzhen

3

3

guangzhou

1

表team

id

name

1

No.1

2

No.2

 

select region.*, team.* from region,teamwhere region.team_id = team.id;

id

name

team_id

id

name

3

guangzhou

1

1

no.1

1

beijing

2

2

no.2

2

shenzhen

3

3

no.3

 

一对多:

表teacher

id

name

1

lisi

2

zhanshan

表course

Id

name

teacher_id

1

python

1

2

web

1

3

java

1

4

c++

2

 

select teacher.*,course.* fromteacher,course where teacher.id=course.teacher_id;

id

name

id

name

teacher_id

1

lisi

1

python

1

1

lisi

2

web

1

1

lisi

3

java

1

2

zhanshan

4

c++

2

 

 

多对多:

表student

id

name

1

zhanshan

2

lisi

3

wangwu

表course

Id

name

teacher_id

1

python

1

2

web

1

3

java

1

4

c++

2

表screlation

id

sid

cid

1

1

1

2

1

2

3

2

1

4

3

1

5

3

3

 

selectstudent.name,course.name,screlation.* from student,course,screlation wherescrelation.sid=student.id and screlation.cid=course.id;

 

name

name

id

sid

cid

zhanshan

python

1

1

1

Zhanshan

Web

2

1

2

Lisi

Python

3

2

1

Wangwu

Python

4

3

1

wangwu

java

5

3

3

 

总结:

  一对一和一对多关系,可以在原有的数据表中增加字段来实现

  多对多关系,通过新建一张表来实现这样的关系

 

7-3 实战:留言板(二)

目标:

  使用Flask框架以及Flask-SQLAlchemy扩展,将用户的留言板和用户信息进行连接,使其他用户可以看到某一用户的所有留言。

 

代码:

# model.py 一对多关系

class Item(db.Model):

           id= db.Column(db.Integer,primary_key=True)

           content= db.Column(db.String(32))

           sender_id= db.Column(db.Integer)

           def__init__(self,content,sender_id): #创建表

                     self.content= content

                     self.sender_id= sender_id

           defadd(self): #数据库插入

                     try:

                                db.session.add(self)

                                db.session.commit()

                                returnself.id

                     exceptException,e:

                                db.session.rollback()

                                returne

                     finally:

                                return0

 

演示:

C:\Users\Administrator\work\PythonSpace\PythonWeb\MessageBoard02>python

Python 2.7.11 (v2.7.11:6d1b6a68f775,Dec  5 2015, 20:32:19) [MSC v.1500 32 bit(

Intel)] on win32

Type "help","copyright", "credits" or "license" for moreinformation.

>>> from model import db

>>> db.create_all()

>>> from model import User,Item

>>> u=User("yx01","012")

>>> u.add()

0

>>>a=User.query.filter_by(username="yx01").first()

>>> a

<model.User object at 0x030E5A50>

>>> a.id

9L

>>> i=Item("12345",9)

>>> i.add()

0

>>> i=Item("3456",9)

>>> i.add()

0

>>> list=[]

>>>list=Item.query.filter_by(sender_id=a.id).all()

>>> list

[<model.Item object at 0x03090ED0>,<model.Item object at 0x03090FF0>]

>>> for e in list:

...    print e.content

...

12345

3456

>>> 

 

# main.py

@app.route("/search",methods=['GET','POST'])

def search():

           ifrequest.method=='POST':

                     un=request.form['username']

                     u=User.query.filter_by(username=un).first()

                     l=[]

                     l=Item.query.filter_by(sender_id=u.id).all()

                     returnrender_template("search.html",content=l)

           returnrender_template("search.html")

 

//search.html

<<!DOCTYPE html>

<html>

<head>

           <title></title>

</head>

<body>

           <divalign="center">

           <h1>MessageBoard</h1>

           {%for message in content %} {{message.content}}<br/>{% endfor %}

           <formmethod="POST">

                     <inputtype="text" name="username" placeholder="Input theusername you want to search">

                     <br/>

                     <inputtype="submit" value="Submit"/>

                     <inputtype="reset" value="reset"/>

           </form>

           </div>

</body>

</html>

 

# model.py 多对多关系

class UIRelation(db.Model):

           id=db.Column(db.Integer,primary_key=True)

           uid=db.Column(db.Integer)

           iid=db.Column(db.Integer)

 

总结:

关系

如何设计简单的关系

使用SQL语句处理关系

使用Flask-SQLAlchemy扩展处理关系

 

 


 

8 发布 Web 应用及补充知识

8-1 将 Web 应用发布到服务器

Web应用的工作流程:

  客户端请求Web服务器,服务器返回结果

 

对服务器(硬件)的要求:

  网络访问

  可见的IP

  一定的存储空间和处理能力

 

选择云计算:

  稳定性更佳

  弹性和扩展性

  安全

  成本低廉

 

演示:以阿里云为例部署Web应用

目录:将上一节课所写的web应用部署到阿里云服务器上,如条件允许,可以分别在Windows操作系统和Linux操作系统上完成。

 

部署云服务器:

1)https://www.aliyun.com/

管理控制台 -> 云服务器ECS ->选择地区的云服务器-> 创建实例

2)ssh远程到云服务器

3)Yummy FTP上传文件 SFTP(22)

4)使用vim修改 app.run(host=’0.0.0.0’,port=8080)来监听所有的端口

 

部署云数据库:

https://www.aliyun.com/

管理控制台-> 云数据库RDS

 

8-2 Web 应用的模块化——蓝图

模块化– 分割,连接

 

Flask中的模块化方案 – 蓝图

  通过蓝图,一个大型应用可以实例化一个应用对象,初始化几个拓展,并注册几个蓝图。

  通过蓝图提供模板过滤器、静态文件等功能。一个蓝图不一定要实现应用或者视图函数。

  可以通过URL前缀和/或者子域名来注册一个蓝图。

 

演示:用户和文章的拆分

目标:使用Flask中Blueprint(蓝图),将用户模块和文章模块进行分离。通过不同的URL来进行区分。

如www.*.com.user/1访问用户的信息,而www.*.com/article/1访问1号文章的信息。

 

代码:

# user.py

from flask import Blueprint

from model import User

 

user=Blueprint('user',__name__)

 

@user.route('/<int:userid>')

def showUser(userid):

           u=User.query.filter_by(id=userid).first()

           returnu.getUsername()

 

# model.py

class User(db.Model):

           ……

           defgetUsername(self):

                     returnself.username

 

# main.py

app.register_blueprint(user,url_prefix='/user')

 

8-3 RESTful API 的设计

REST = Representational State Transfer

每个URL代表一种资源

客户端和服务端传递这种资源的表现层

客户端通过四个HTTP动词来进行状态转化

通常传递XML或JSON格式的文本

 

四个HTTP动词

  GET(SELECT):从服务器取出资源(一项或多项)

  POST(CREATE):在服务器新建一个资源

 PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)

 PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)

 DELETE(DELETE):从服务器删除资源

 

演示:设计简单的RESTful API

目标:使用Flask-Rest插件完成一个简单的RESTful API。返回JSON格式的文本。并进行测试。

 

安装:pip install flask-restful

检验:

 >python

 >>>from flask.ext import restful

 

代码:

# userAPI.py

#coding:utf-8

 

from flask.ext.restful import reqparse,Resource

from JsonObject import JsonObject

from model import User

auth=reqparse.RequestParser()

 

class Authentication(Resource):

           defget(self):

                     pass

           defpost(self):

                     auth.add_argument('username',required=True,help="Usernameis Required")

                     auth.add_argument('password',required=True,help="Passwordis Required")

                     args=auth.parse_args()

                     username= args['username']

                     password= args['password']

                     u= User(username,password)

                     jsobj= JsonObject()

                     ifu.isExisted():

                                jsobj.put("code",1)

                                jsobj.put("desc","UserExisted")

                     else:

                                jsobj.put("code",2)

                                jsobj.put("desc","UserNot Existed")

                     returnjsobj.getJson(),200

 

#jsonObject.py

import json

class JsonObject():

   def __init__(self):

       self.dic={}

   def put(self,key,value):

       self.dic[key]=value

   def get(self,key):

       return self.dic[key]

   def getJson(self):

       return json.dumps(self.dic,ensure_ascii=False).replace('}"','}')

   def getDic(self):

       return self.dic

 

# userAPI.py

#coding:utf-8

from flask.ext.restful import reqparse,Resource

from JsonObject import JsonObject

from model import User

auth=reqparse.RequestParser()

 

class Authentication(Resource):

           defget(self):

                     pass

           defpost(self):

                     auth.add_argument('username',required=True,help="Usernameis Required")

                     auth.add_argument('password',required=True,help="Passwordis Required")

                     args=auth.parse_args()

                     username= args['username']

                     password= args['password']

                     u= User(username,password)

                     jsobj= JsonObject()

                     ifu.isExisted():

                                jsobj.put("code",1)

                                jsobj.put("desc","UserExisted")

                     else:

                                jsobj.put("code",2)

                                jsobj.put("desc","UserNot Existed")

                     returnjsobj.getJson(),200

 

#server.py

#coding:utf-8

from flask import Flask

from flask.ext.restful import Api

from userAPI import *

 

app = Flask(__name__)

api = Api(app)

 

import sys

reload(sys)

sys.setdefaultencoding('utf-8')

 

api.add_resource(Authentication,'/auth')

 

if __name__=='__main__':

           app.run(port=8080)

 

在windows中,使用AdvancedRest Client进行四个HTTP动词的测试

8-4 数据库的修改和迁移

数据库的修改:

  修正数据库的需求

  保持数据的完整性

  尽可能减少服务中断时间

 Alembic、Flask-Migrate等插件

 

演示:修改数据库

目标:使用一些第三方插件增加、删除数据库中的字段。

>pip install flask-migrate

>python

>>>from flask.ext import migrate

 

C:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate>python migrater.py

db init  //初始化步骤,建立仓库,在migrations目录中建立一堆文件

C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py:800:UserWarning: SQL

ALCHEMY_TRACK_MODIFICATIONS addssignificant overhead and will be disabled by de

fault in the future.  Set it to True to suppress this warning.

 warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overheadand wi

ll be disabled by default in thefuture.  Set it to True to suppress thiswarnin

g.')

Creating directoryC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\

migrations ... done

Creating directoryC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\

migrations\versions ... done

GeneratingC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\migratio

ns\alembic.ini ... done

GeneratingC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\migratio

ns\env.py ... done

Generating C:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\migratio

ns\env.pyc ... done

GeneratingC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\migratio

ns\README ... done

GeneratingC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\migratio

ns\script.py.mako ... done

Please editconfiguration/connection/logging settings in 'C:\\Users\\Administrat

or\\work\\PythonSpace\\PythonWeb\\4DBMigrate\\migrations\\alembic.ini'before pr

oceeding.

 

C:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate>python migrater.py

db migrate //对数据库进行检测

C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py:800:UserWarning: SQL

ALCHEMY_TRACK_MODIFICATIONS addssignificant overhead and will be disabled by de

fault in the future.  Set it to True to suppress this warning.

 warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overheadand wi

ll be disabled by default in thefuture.  Set it to True to suppress thiswarnin

g.')

C:\Python27\lib\site-packages\sqlalchemy\engine\default.py:450:Warning: Incorre

ct string value:'\xD6\xD0\xB9\xFA\xB1\xEA...' for column 'VARIABLE_VALUE' at ro

w 475

 cursor.execute(statement, parameters)

INFO [alembic.runtime.migration] Context impl MySQLImpl.

INFO [alembic.runtime.migration] Will assume non-transactional DDL.

INFO [alembic.autogenerate.compare] Detected added table 'ui_relation'

INFO [alembic.autogenerate.compare] Detected removed table u'ipdata'

INFO [alembic.autogenerate.compare] Detected removed table u'student'

INFO [alembic.autogenerate.compare] Detected removed table u'entry'

INFO [alembic.autogenerate.compare] Detected added column 'item.context'

INFO [alembic.autogenerate.compare] Detected removed column 'item.content'

INFO [alembic.autogenerate.compare] Detected added column 'user.age'

INFO [alembic.autogenerate.compare] Detected added column 'user.male'

GeneratingC:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate\migratio

ns\versions\5d134dc231a4_.py ... done

 

C:\Users\Administrator\work\PythonSpace\PythonWeb\4DBMigrate>python migrater.py

db upgrade //修改表字段,而这一操作不会损坏表结构,对数据库的升级非常有帮助

C:\Python27\lib\site-packages\flask_sqlalchemy\__init__.py:800:UserWarning: SQL

ALCHEMY_TRACK_MODIFICATIONS addssignificant overhead and will be disabled by de

fault in the future.  Set it to True to suppress this warning.

 warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overheadand wi

ll be disabled by default in thefuture.  Set it to True to suppress thiswarnin

g.')

C:\Python27\lib\site-packages\sqlalchemy\engine\default.py:450:Warning: Incorre

ct string value:'\xD6\xD0\xB9\xFA\xB1\xEA...' for column 'VARIABLE_VALUE' at ro

w 475

 cursor.execute(statement, parameters)

INFO [alembic.runtime.migration] Context impl MySQLImpl.

INFO [alembic.runtime.migration] Will assume non-transactional DDL.

INFO [alembic.runtime.migration] Running upgrade  -> 5d134dc231a4, empty messag

e

 

代码:

#migrater.py

from model import db

from model import app

from flask.ext.script import Manager

from flask.ext.migrate import Migrate,MigrateCommand

 

migrate = Migrate(app,db)

manager = Manager(app)

manager.add_command('db',MigrateCommand)

 

if __name__ == '__main__':

           manager.run()

 

 

#model.py

#coding:utf-8

 

from flask import Flask

from flask.ext.sqlalchemy import SQLAlchemy

 

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] ='mysql://root:root@localhost/test'

db = SQLAlchemy(app)

 

class User(db.Model):

           id= db.Column(db.Integer,primary_key=True)

           username= db.Column(db.String(32),unique=True)

           password= db.Column(db.String(32))

           male= db.Column(db.String(2))

           age= db.Column(db.Integer)

           def__init__(self,username,password):

                     self.username= username

                     self.password= password

           defadd(self):

                     try:

                                db.session.add(self)

                                db.session.commit()

                                returnself.id

                     exceptException,e:

                                db.session.rollback()

                                returne

                     finally:

                                return0

           defisExisted(self):

                     temUser=User.query.filter_by(username=self.username,password=self.password).first()

                     iftemUser is None:

                                returnFalse

                     else:

                                returnTrue

           defgetUsername(self):

                     returnself.username

 

class Item(db.Model):

           id=db.Column(db.Integer,primary_key=True)

           context=db.Column(db.String(128))

           sender_id=db.Column(db.Integer)

           def__init__(self,context,sender_id):

                     self.context=context

                     self.sender_id=sender_id

           defadd(self):

                     try:

                                db.session.add(self)

                                db.session.commit()

                                returnself.id

                     exceptException,e:

                                db.session.rollback()

                                returne

                     finally:

                                return0

 

class UIRelation(db.Model):

           id=db.Column(db.Integer,primary_key=True)

           uid=db.Column(db.Integer)

           iid=db.Column(db.Integer)

 

 

课程总结:

  将应用部署在服务器上

  将应用程序模块化

  构建RESTful API

  使用Flask-Migrate处理数据库升级

0 0