Day04

1.分页器方法

分页器BaseQuery.paginate()pageper_pageFalsePaginationitemspages获取总页数prev_num上一页的页码has_prev是否有上一页next_num下一个页码has_next是否有下一页iter_pages

李晶:

__init__.py
from flask import Flask
from App import settings
from App.ext import init_ext
def create_app(envname):app = Flask(__name__)app.config.from_object(settings.ENV_NAME.get(envname))init_ext(app)return appext.py
# flask-script
# flask-blueprint
# flask-session
# flask-sqlalchemy
# flask-migrate
from flask_bootstrap import Bootstrap
from flask_debugtoolbar import DebugToolbarExtension
from flask_migrate import Migrate
from flask_session import Session
from App.models import dbdef init_ext(app):app.config['SECRET_KEY']='110'app.config['SESSION_TYPE']='redis'Session(app=app)db.init_app(app=app)migrate = Migrate()migrate.init_app(app=app,db=db)Bootstrap(app=app)app.debug = True# debugtoolbardebugtoolbar = DebugToolbarExtension()debugtoolbar.init_app(app=app)models.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()class Emp(db.Model):id = db.Column(db.Integer,primary_key=True,autoincrement=True)name = db.Column(db.String(32))age = db.Column(db.Integer,default=18)gender = db.Column(db.String(2))salary = db.Column(db.Float)class Parent(db.Model):id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(30),unique=True)# Child对应的表  backref 子表外键描述需要children=db.relationship("Child",backref="parent",lazy=True)class Child(db.Model):id = db.Column(db.Integer, primary_key=True,autoincrement=True)name = db.Column(db.String(30), unique=True)parent_id = db.Column(db.Integer, db.ForeignKey('parent.id'))class User(db.Model):id = db.Column(db.Integer,primary_key=True,autoincrement=True)name = db.Column(db.String(32))age = db.Column(db.Integer,default=18)class Movie(db.Model):id = db.Column(db.Integer,primary_key=True,autoincrement=True)name = db.Column(db.String(32))class Collection(db.Model):id = db.Column(db.Integer,primary_key=True,autoincrement=True)u_id = db.Column(db.Integer,db.ForeignKey(User.id))m_id = db.Column(db.Integer,db.ForeignKey(Movie.id))setting.pydef get_database_uri(DATABASE):dialect = DATABASE.get('dialect')driver = DATABASE.get('driver')username = DATABASE.get('username')password = DATABASE.get('password')host = DATABASE.get('host')port = DATABASE.get('port')database = DATABASE.get('database')return '{}+{}://{}:{}@{}:{}/{}'.format(dialect,driver,username,password,host,port,database)class Config():Test = FalseDebug = FalseSQLALCHEMY_TRACK_MODIFICATIONS = Falseclass DevelopConfig(Config):Debug = TrueDATABASE={'dialect':'mysql','driver':'pymysql','username':'root','password':'1234','host':'localhost','port':'3306','database':'flaskday04',}SQLALCHEMY_DATABASE_URI=get_database_uri(DATABASE)ENV_NAME={'develop':DevelopConfig
}views.py
from flask import Blueprint, render_template, request, redirect, url_forfrom App.models import Emp, db, Parent, Child, Collectionblue = Blueprint('blue',__name__)@blue.route('/')
def hello_world():return 'Hello World!'@blue.route('/list/')
def list():emps = Emp.query.all()return render_template('userList.html',emps=emps)@blue.route('/toadd/')
def toadd():return render_template('add.html')@blue.route('/add/',methods=['get','post'])
def add():name = request.form.get('name')age = request.form.get('age')gender = request.form.get('gender')salary = request.form.get('salary')print(name,age,gender,salary)emp = Emp()emp.name = nameemp.age = ageemp.gender = genderemp.salary = salarydb.session.add(emp)db.session.commit()return redirect(url_for('blue.list'))@blue.route('/delete/')
def delete():id = request.args.get('id')emp = Emp.query.get(id)db.session.delete(emp)db.session.commit()return redirect(url_for('blue.list'))@blue.route('/toupdate/')
def toupdate():id = request.args.get('id')emp = Emp.query.get(id)return render_template('update.html',emp=emp)@blue.route('/update/',methods=['get','post'])
def update():id = request.args.get('id')emp = Emp.query.get(id)name = request.form.get('name')age = request.form.get('age')gender = request.form.get('gender')salary = request.form.get('salary')emp.name=nameemp.age = ageemp.gender = genderemp.salary = salarydb.session.add(emp)db.session.commit()return redirect(url_for('blue.list'))# 添加主键对象  会不会直接将外键添加
@blue.route('/saveparent/')
def saveparent():p = Parent()p.name = '张三'c = Child()c.name = '张四'c1 = Child()c1.name = '王五'p.children=[c,c1]db.session.add(p)db.session.commit()return 'add success'# 从查主
# select * from parent where  id = (select pid from Child where id = 1)
# 主查从
# select * from Child where pid = (select id from Parent where id = 1)
# 查询@blue.route('/getparent/')
def getparent():p = Parent.query.filter(Child.parent_id == 1).first()# print(p[0].name)print(p.name)return 'ok'@blue.route('/getchild/')
def getchild():clist = Child.query.filter(Parent.id == 1)for c in clist:print(c.name)return 'ok'# 多对多的添加
# 将用户id和电影id 获取      然后去数据库中查找 是否存在 如果存在那就告诉已经添加到购物车
# 否则 添加到购物车
@blue.route('/addcollection/')
def addcolletion():u_id = int(request.args.get('u_id'))m_id = int(request.args.get('m_id'))print(u_id,m_id)c = Collection.query.filter(Collection.u_id == u_id).filter(Collection.m_id==m_id)if c.count() > 0:return '已经添加到购物车'else:c1 = Collection()c1.u_id = u_idc1.m_id = m_iddb.session.add(c1)db.session.commit()return 'ok'@blue.route('/bootstrapDemo/')
def bootstrapDemo():# emps = Emp.query.all()page = int(request.args.get('page',1))per_page = int(request.args.get('per_page',2))pagination = Emp.query.paginate(page=page,per_page=per_page,error_out=False)return render_template('bootstrapDemo.html',pagination=pagination)manager.py
from flask_migrate import MigrateCommand
from flask_script import Managerfrom App import create_app
from App.views import blueapp = create_app('develop')manager = Manager(app=app)app.register_blueprint(blueprint=blue)manager.add_command('db',MigrateCommand)if __name__ == '__main__':manager.run()

templates:

add.html
<html><head><title>regist</title><meta http-equiv="content-type" content="text/html;charset=utf-8"/><link rel="stylesheet" type="text/css" href="/static/css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">Main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>注册</h1><form action="{{ url_for('blue.add') }}" method="post"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">用户名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="name" /></td></tr><tr><td valign="middle" align="right">年龄:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="age" /></td></tr><tr><td valign="middle" align="right">性别:</td><td valign="middle" align="left">男<input type="radio" class="inputgri" name="gender" value="男"checked="checked" />女<input type="radio" class="inputgri" name="gender" value="女" /></td></tr><tr><td valign="middle" align="right">薪水:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="salary" /></td></tr></table><p><input type="submit" class="button" value="添加" /></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126.com</div></div></div></body>
</html>bootstrapDemo.py
{% extends 'bootstrap/base.html' %}{% block navbar %}<nav class="navbar navbar-inverse"><div class="container-fluid"><!-- Brand and toggle get grouped for better mobile display --><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse"data-target="#bs-example-navbar-collapse-1" aria-expanded="false"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="#">万锋集团</a></div><!-- Collect the nav links, forms, and other content for toggling --><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav"><li class="active"><a href="#">员工风采 <span class="sr-only">(current)</span></a></li><li><a href="#">企业文化</a></li></ul><form class="navbar-form navbar-left"><div class="form-group"><input type="text" class="form-control" placeholder="请输入员工姓名"></div><button type="submit" class="btn btn-default">搜索</button></form><ul class="nav navbar-nav navbar-right"><li><a href="#">注册</a></li><li><a href="#">登录</a></li></ul></div><!-- /.navbar-collapse --></div><!-- /.container-fluid --></nav>{% endblock %}{% block content %}<div class="container"><div class="jumbotron"><h1>welcome to red langman</h1><p>...</p><p><a class="btn btn-primary btn-lg" href="#" role="button">go</a></p></div></div><div align="center"><table width="800" height="150" border="1" align="center"><tr><th>id</th><th>name</th><th>age</th><th>gender</th><th>salary</th><th>operate</th></tr>{% for emp in pagination.items %}<tr><td>{{ emp.id }}</td><td>{{ emp.name }}</td><td>{{ emp.age }}</td><td>{{ emp.gender }}</td><td>{{ emp.salary }}</td><td><a>删除</a><a>修改</a></td></tr>{% endfor %}</table></div><div align="center"><nav aria-label="Page navigation"><ul class="pagination"><li>{% if pagination.has_prev %}<a href="{{ url_for('blue.bootstrapDemo') }}?page={{ pagination.prev_num }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a>{% else %}<a href="#" aria-label="Previous"><span aria-hidden="true">上一页</span></a>{% endif %}</li>{% for p in pagination.iter_pages() %}<li><a href="#">{{ p }}</a></li>{% endfor %}<li>{% if pagination.has_next %}<a href="{{ url_for('blue.bootstrapDemo') }}?page={{ pagination.next_num }}" aria-label="Next"><span aria-hidden="true">下一页</span></a>{% else %}<a href="#" aria-label="Next"><span aria-hidden="true">下一页</span></a>{% endif %}</li></ul></nav></div>{% endblock %}login.html
<html><head><title>login</title><meta http-equiv="content-type" content="text/html;charset=utf-8" /><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">Main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>login</h1><form action="userList.html" method="post"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">username:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="username" /></td></tr><tr><td valign="middle" align="right">password:</td><td valign="middle" align="left"><input type="password" class="inputgri" name="pwd" /></td></tr></table><p><input type="submit" class="button" value="&nbsp;确定&nbsp;" /><a href="regist.html">还没有帐户,请点击这儿注册</a></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126.com</div></div></div></body>
</html>regist.html
<html><head><title>regist</title><meta http-equiv="content-type" content="text/html;charset=utf-8"/><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">Main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>注册</h1><form action="login.html" method="post"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td valign="middle" align="right">用户名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="username" /></td></tr><tr><td valign="middle" align="right">真实姓名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="name" /></td></tr><tr><td valign="middle" align="right">密码:</td><td valign="middle" align="left"><input type="password" class="inputgri" name="pwd" /></td></tr><tr><td valign="middle" align="right">年龄:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="age" /></td></tr><tr><td valign="middle" align="right">性别:</td><td valign="middle" align="left">男<input type="radio" class="inputgri" name="sex" value="m"checked="checked" />女<input type="radio" class="inputgri" name="sex" value="f" /></td></tr><tr><td valign="middle" align="right">电话:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="phone" /></td></tr><tr><td valign="middle" align="right">对方要求:</td><td valign="middle" align="left"><textarea rows="5" cols="30" name="ask" style="resize:none;"></textarea></td></tr><tr><td valign="middle" align="right">验证码:<img id="num" src="checkCode" /><a href="javascript:;"onclick="document.getElementById('num').src = 'checkCode?'+(new Date()).getTime()">换一张</a></td><td valign="middle" align="left"><input type="text" class="inputgri" name="number" /></td></tr></table><p><input type="submit" class="button" value="Submit &raquo;" /></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126.com</div></div></div></body>
</html>update.html
<html><head><title>regist</title><meta http-equiv="content-type" content="text/html;charset=utf-8"/><link rel="stylesheet" type="text/css" href="/static/css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">Main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>注册</h1><form action="{{ url_for('blue.update') }}?id={{ emp.id }}" method="post"><table cellpadding="0" cellspacing="0" border="0"class="form_table"><tr><td>id</td><td><input type="text" class="inputgri" name="id" value="{{ emp.id }}" readonly="true"></td></tr><tr><td valign="middle" align="right">用户名:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="name" value="{{ emp.name }}"/></td></tr><tr><td valign="middle" align="right">年龄:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="age" value="{{ emp.age }}" /></td></tr><tr><td valign="middle" align="right">性别:</td><td valign="middle" align="left">{% if emp.gender == '男' %}男<input type="radio" class="inputgri" name="gender" value="男"checked="checked" />女<input type="radio" class="inputgri" name="gender" value="女" />{% else %}男<input type="radio" class="inputgri" name="gender" value="男"/>女<input type="radio" class="inputgri" name="gender" value="女"checked="checked" />{% endif %}</td></tr><tr><td valign="middle" align="right">薪水:</td><td valign="middle" align="left"><input type="text" class="inputgri" name="salary" value="{{ emp.salary }}"/></td></tr></table><p><input type="submit" class="button" value="修改" /></p></form></div></div><div id="footer"><div id="footer_bg">ABC@126.com</div></div></div></body>
</html>userDetail.html
<html><head><title>update Emp</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">Main</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>User Detail:</h1><table class="table"><tr><td>姓名</td><td>电话</td></tr><tr><td>zhangshan</td><td>010-12345678</td></tr></table><h1>对方要求:</h1><table><tr><td colspan="2"><textarea cols="80" style="border:0px;resize:none;"></textarea></td></tr></table><br/><h1>Load Photo:</h1><form action="userDetail.html" method="post"enctype="multipart/form-data">Upload File Name:<input type="file" name="file1" /><input type="submit" value="confirm" /></form><h1>view photo:</h1><table><tr><td><img src="upload/t1.jpg" width="300"height="200" /></td></tr></table></div><input type="button" onclick="location='userList.html'" value="查看所有用户"/></div><div id="footer"><div id="footer_bg">ABC@126.com</div></div></div></body>
</html>userlist.html
<html><head><title>emplist</title><meta http-equiv="content-type" content="text/html;charset=utf-8"/><link rel="stylesheet" type="text/css" href="/static/css/style.css" /><script type="text/javascript">function toadd() {{#    企业级开发中不要直接的跳转到某一个页面  必须要通过请求来跳转#}{#    window.location.href = '/toadd/'#}window.open('/toadd/',target='_self')}</script></head><body><div id="wrap"><div id="top_content"><div id="header"><div id="rightheader"><p>2009/11/20<br /></p></div><div id="topheader"><h1 id="title"><a href="#">主页面</a></h1></div><div id="navigation"></div></div><div id="content"><p id="whereami"></p><h1>Welcome!</h1><table class="table"><tr class="table_header"><td>ID</td><td>姓名</td><td>性别</td><td>年龄</td><td>薪水</td><td>操作</td></tr>{% for emp in emps %}<tr class="row1"><td>{{ emp.id }}</td><td>{{ emp.name }}</td><td>{{ emp.gender }}</td><td>{{ emp.age }}</td><td>{{ emp.salary }}</td><td>{#  /delete/?id=1  #}<a href="{{ url_for('blue.delete') }}?id={{ emp.id }}">删除</a><a href='{{ url_for('blue.toupdate') }}?id={{ emp.id }}'>修改</a></td></tr>{% endfor %}</table><p><input type="button" class="button" value="添加员工"onclick="toadd();" /></p></div></div><div id="footer"><div id="footer_bg">ABC@126.com</div></div></div></body>
</html>

2.flask-bootstrap

插件安装pip install  flask-bootstrap
ext中初始化Bootstrap(app=app)bootstrap案例--bootstrap模板   {% extends ‘bootstrap/base.html’%}

3.FLASK-DEBUGTOOLBAR

辅助调试插件
安装pip install flask-debugtoolbar
初始化  ext app.debug = True (最新版本需要添加)debugtoolbar = DebugToolBarExtension()debugtoolbar.init_app(app=app)

4.缓存flask-cache

1 缓存目的:缓存优化加载,减少数据库的IO操作
2 实现方案数据库文件内存内存中的数据库 Redis
3 实现流程从路由函数进入程序路由函数到视图函数视图函数去缓存中查找缓存中找到,直接进行数据返回如果没找到,去数据库中查找查找到之后,添加到缓存中返回到页面上
4 使用安装 flask-cachepip  install flask-cache初始化指定使用的缓存方案cache = Cache(config={'CACHE_TYPE':默认是simple})cache.init_app(app=app)使用在路由的下面添加@cache.cached(timeout=30)要配置configTYPE还可以配置各种缓存的配置信息cache=Cache(config={'CACHE_KEY_PREFIX':'python'})用法装饰器@cache.cached(timeout=xxx)原生getset

5.钩子

before_request

6.四大内置对象

四大内置对象request- 请求的所有信息session- 服务端会话技术的接口config当前项目的配置信息模板中可以直接使用config在python代码中current_app.config当前运行的app使用记得是在初始化完成之后用在函数中gglobal  全局可以帮助开发者实现跨函数传递数据

7.路径

 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))init中app = Flask(__name__,static_folder=static_folder)static_folder=os.path.join(settings.BASE_DIR,'static')

8.Json

JSONjson数据不可以直接返回json例子   $.getJsonjquery  cdn

Day05

1.前后端分离

RESTful API

什么是REST

一种软件架构风格、设计风格、而不是标准,只是提供了一组设计原则和

约束条件。它主要用户客户端和服务器交互类的软件。

基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。

REST全称是Representational State Transfer,表征性状态转移。

首次在2000年Roy Thomas Fielding的博士论文中出现,Fielding是一个

非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者,

Apache服务器软件的作者之一,Apache基金会的第一任主席。所以,

他的这篇论文一经发表,就引起了广泛的关注。

论文:

本文研究计算机科学两大前沿----软件和网络----的交叉点。长期以来,

软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估

不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统

之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,

那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。

我这篇文章的写作目的,就是想在符合架构原理的前提下,

理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、

性能好、适宜通信的架构。

REST爆发

其实在REST架构推出的十几年间,它并没有一路高歌的发展,

真正的大范围推广是在2013年之后,伴随着移动端的飞速发展,

越来越多人的开始意识到,网站即软件,而且是一种新型的软件。

这种"互联网软件采用"客户端/服务器"模式,也就是我们常说的C/S模式,

这一切建立在分布式体系上,通过互联网通信,具有高延时,高并发等特点。

网站开发,完全采用软件开发开发的模式。但传统上,软件和网络是两个

不同的领域,很少有交集,软件开发主要针对单机环境,网络则主要

研究系统之间的通信。我们需要考虑的是如何开发在互联网环境中使用软件。

理解RESTful

要理解RESTful架构,最好的就是去理解它的单词 Representational State

Transfer 到底是什么意思,它的每一个词到底要表达什么。

REST的释义,“表现层状态转化”,其实这省略了主语。“表现层”其实指的是

“资源(Resource)”的“表现层”。

资源(Resource)

所谓“资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。

它可以是一段文本,一张图片,一首歌曲,一种服务,总之就是一个具体的实例

。你可以使用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI

。要获取这个资源,访问它的URI就可以了,因此URI就成了每一个资源

的地址或独一无二的识别符。所谓“上网”就是与互联网上一系列的“资源”互动

,调用它们的URI。

表现层(Representation)

“资源”是一种信息实体,它可以有多种外在表现形式。我们把“资源”

具体呈现出来的形式,叫做它的”表现层“(Representation)。

URI只代表资源的实体,不代表它的形式。严格地说,有些网站最后的”

.html“后缀名是不必要的,因为这个后缀表示格式,属于”表现层“范畴,

而URI应该只代表”资源“的位置。它的具体表现形式,应该在HTTP请求

头的信息中使用Accept和Content-Type字段指定。

状态转换(State Transfer)

访问一个网站,就代表客户端和服务端的一个互动过程。在这个过程中,

势必涉及到数据和状态的变化。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,

所有的状态都保存在服务端。因此,如果客户端想要操作服务器,

就必须通过某种手段,让服务器端发生”状态转换(State Transfer)“。

而这种转换是建立在表现层之上的,所以就是”表现层状态转化“。

客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议中,

四个表示操作方式的动词:GET,POST,PUT,DELETE。

它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源

(也可用于更新资源),PUT用来更新资源,DELETE用来删除资源

到底什么是RESTful架构

每一个URI代表一种资源

客户端和服务器之间,传递这种资源的某种表现层

客户端通过四个HTTP动词,对服务端资源进行操作,实现”表现层状态转换“

RESTful API设计

协议

API与用户的通信协议,通常使用HTTP(S)协议。

域名

应该尽量将API部署在专用域名之下。

http://api.rock.com

如果确定API很简单,不会有大规模扩充,可以考虑放在主域名之下。

http://www.rock.com/api/

版本

应该将API的版本号放入URL。

http://api.rock.com/v1/

也有做法是将版本号放在HTTP的头信息中,但不如放在URL中方便和直观。

GITHUB是这么搞的。

路径(Endpoint)

路径又称”终点“(endpoint),表示API的具体网址。

在RESTful架构中,每个网址代表一种资源(Resource),

所以网址中不能有动词,只能有名词,而且所用的名词往往与

数据库的表格名对应。一般来说,数据库中的表都是同种记录的”集合“

(collection),所以API中的名词也应该使用复数。

HTTP动词

对于资源的具体操作类型,由HTTP动词表示。

HTTP常用动词

GET(SELECT):从服务器取出资源

POST(CREATE or UPDATE):在服务器创建资源或更新资源

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

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

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

HEAD:获取资源的元数据

OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的、

示例

GET /students:获取所有学生

POST /students:新建学生

GET /students/id:获取某一个学生

PUT /students/id :更新某个学生的信息(需要提供学生的全部信息)

PATCH /students/id:更新某个学生的信息(需要提供学生变更部分信息)

DELETE /students/id:删除某个学生

过滤信息(Filtering)

如果记录数量过多,服务器不可能将它们返回给用户。API应该提供参数,

过滤返回结果。

?limit=10

?offset=10

?page=2&per_page=20

?sortby=name&order=desc

?student_id=id

参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复,

比如 GET /students/id 和 ?student_id=id

状态码

服务器向用户返回的状态码和提示信息,常见的有以下一些地方

200 OK - [GET]:服务器成功返回用户请求的数据

201 CREATED -[POST/PUT/PATCH]:用户新建或修改数据成功

202 Accepted - [*] :表示一个请求已经进入后台排队(异步任务)

204 NO CONTENT - [DELETE]:表示数据删除成功

400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误

401 Unauthorized - [*] :表示用户没有权限(令牌,用户名,密码错误)

403 Forbidden - [*]:表示用户得到授权,但是访问是被禁止的

404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录

406 Not Acceptable - [*]:用户请求格式不可得

410 Gone - [GET] :用户请求的资源被永久移除,且不会再得到的

422 Unprocesable entity -[POST/PUT/PATCH]:当创建一个对象时,

发生一个验证错误

500 INTERNAL SERVER EROR - [*] :服务器内部发生错误

错误处理

如果状态码是4xx,就应该向用户返回出错信息。一般来说,

返回的信息中将error做为键名

返回结果

针对不同操作,服务器想用户返回的结果应该符合以下规范

GET /collection:返回资源对象的列表(数组,集合)

GET /collection/id:返回单个资源对象

POST /collection:返回新生成的资源对象

PUT /collection/id:返回完整的资源对象

PATCH /collection/id:返回完整的资源对象

DELETE /collection/id:返回一个空文档

使用链接关联资源

RESTful API最好做到Hypermedia,即返回结果中提供链接,

连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

{

"link": {"rel":   "collection https://www.rock.com/zoostudents","href":  "https://api.rock.com/students","title": "List of students","type":  "application/vnd.yourformat+json"}

}

rel:表示这个API与当前网址的关系

href:表示API的路径

title:表示API的标题

type:表示返回的类型

其它

服务器返回的数据格式,应该尽量使用JSON

API的身份认证应该使用OAuth2.0框架

总之

  为什么会出现Restful

在Restful之前的操作:

saveUser

http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据

http://127.0.0.1/user/save POST 新增用户

http://127.0.0.1/user/update POST 修改用户信息

http://127.0.0.1/user/delete GET/POST 删除用户信息

RESTful用法:根据请求提交方式的不同 然后执行对应的方法

http://127.0.0.1/user/1 GET 根据用户id查询用户数据

http://127.0.0.1/user POST 新增用户

http://127.0.0.1/user PUT 修改用户信息

http://127.0.0.1/user DELETE 删除用户信息

if request.method = ‘get’:

User.query.first()

else request.method = ‘post’:

之前的操作是没有问题的,大神认为是有问题的,有什么问题呢?

你每次请求的接口或者地址,都在做描述,例如查询的时候用了query,

新增的时候用了save,其实完全没有这个必要,我使用了get请求,就是查询.

使用post请求,就是新增的请求,我的意图很明显,完全没有必要做描述,

这就是为什么有了restful.

ajax其实质利用浏览器内置ajax对象(xmlhttprequest xhr)

异步的向服务器发送请求

提交的是部分数据

利用返回的数据更新当前页面

整个过程中

页面无刷新

不打断用户的操作

整合网络和软件的一种架构模式
理解Representtational表现层State Transfer状态转换表现层状态转换资源(Resource)每一个URI代表一类资源对整个数据的操作增删改查
RESTful中更推荐使用HTTP的请求谓词(动词)来作为动作标识GETPOSTPUTDELETEPATCH
推荐使用json数据传输状态码200 ok201 created202 Accepted204 删除成功 400 401没有认证403 没有权限404405 406 验证错误422 500设计原则http(s)协议应该有自己专属域名在应用上添加一个api前缀都是名词,复数形式可以将版本号设计进去增量操作/collection/id/? id=xxx

2.原生实现

概念:就是判断不同的请求方式,实现请求方法
高内聚,低耦合高内聚相同的数据操作封装在一起低耦合
MVC 没有模板--前后端分离
使用md5eg:def generate_password(password):hash = hashlib.md5()hash.update(password.encode("utf-8"))return hash.hexdigest()get坑---类型eg:@blue.route("/users/<int:id>/", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])def users(id):if request.method == "GET":page = int(request.args.get("page", default=1))per_page = int(request.args.get("per_page", default=3))users = User.query.paginate(page=page, per_page=per_page, error_out=False).itemsusers_dict = []for user in users:users_dict.append(user.to_dict())data = {"message": "ok","status": "200","data": users_dict}return jsonify(data)posteg:elif request.method == "POST":# 更新或创建username = request.form.get("username")password = request.form.get("password")data = {"message": "ok","status": "422"}if not username or not password:data["message"] = "参数不正确"return jsonify(data), 422user = User()user.u_name = usernameuser.u_password = generate_password(password=password)try:db.session.add(user)db.session.commit()data["status"] = "201"except Exception as e:data["status"] = "901"data["message"] = str(e)return jsonify(data), 422return jsonify(data), 201puteg:elif request.method == "PUT":username = request.form.get("username")password = request.form.get("password")user = User.query.get(id)user.u_name = usernameuser.u_password = generate_password(password)db.session.add(user)db.session.commit()data = {"message": "update success",}return jsonify(data), 201deleteeg:elif request.method == "DELETE":user = User.query.get(id)data = {"message": "delete success"}if user:db.session.delete(user)db.session.commit()return jsonify(data), 204else:data["message"] = "指定数据不存在"return jsonify(data)patcheg:elif request.method == "PATCH":password = request.form.get("password")user = User.query.get(id)user.u_password = generate_password(password)data = {"messgage": "update success"}db.session.add(user)db.session.commit()return jsonify(data), 201

3.flask-restful

框架简化开发

使用

使用安装 pip install flask-restful初始化 urls---在init中调用init_urlsapi = Api()api.add_resource(Hello, "/hello/")Hello是一个类的名字  hello是路由def init_urls(app):api.init_app(app=app)apis--基本用法继承自Resourceclass Hello(Resource):实现请求方法对应函数def get(self):return {"msg": "ok"}def post(self):return {"msg": "create success"}

定制输入输出

定制输入输出输出fields中的类型约束StringIntegerNestedListNested@marshal_with的基本使用类型括号中还允许添加约束attribute指定连接对应名字attribute=名字default设置默认值default=404marshal_with特性- 默认返回的数据如果在预定义结构中不存在,数据会被自动过滤- 如果返回的数据在预定义的结构中存在,数据会正常返回- 如果返回的数据比预定义结构中的字段少,预定义的字段会呈现一个默认值如果类型是Integer  那么默认值是  0如果类型是String  那么默认值是null@marshal_with返回一个类对象@marshal_with返回一个列表输入使用了parser=reqparse.RequestParser()parser.add_argument("c_name", type=str)parser.add_argument("id", type=int, required=True, help="id 是必须的")parse = parser.parse_args()cat_name = parse.get("c_name")id = parse.get("id")print(id)在对象中添加字段对字段添加约束defaultrequired必须的参数helpid是必须的actionaction=appendc_name=tom&c_name=zs继承copy可以对已有字段进行删除和更新继承解析- 在整个项目中,通用字段可以创建一个基parser- 复用已有的部分参数转换数据结构parse_c parser.copy()   parse_c.remove_argument('')

李晶1:

__init__.py
import osfrom flask import Flaskfrom App import settings
from App.ext import init_extdef create_app(envname):# 获取项目路径BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))print(BASE_DIR)templates_folder = os.path.join(BASE_DIR,'templates')print(templates_folder)static_folder = os.path.join(BASE_DIR,'static')print(static_folder)app = Flask(__name__,template_folder=templates_folder,static_folder=static_folder)app.config.from_object(settings.ENV_NAME.get(envname))init_ext(app)return appext.py
# flask-script
# flask-blueprint
# flask-session
# flask-sqlalchemy
# flask-migrate
from flask_bootstrap import Bootstrap
from flask_cache import Cache
from flask_debugtoolbar import DebugToolbarExtension
from flask_migrate import Migrate
from flask_session import Sessionfrom App.models import dbcache = Cache(config={'CACHE_TYPE': 'redis'})def init_ext(app):# 有循环导入问题# app.register_blueprint(blueprint=blue)app.config['SECRET_KEY']='110'app.config['SESSION_TYPE']='redis'Session(app=app)db.init_app(app=app)migrate = Migrate()migrate.init_app(app=app,db=db)Bootstrap(app=app)app.debug = True# debugtoolbardebugtoolbar = DebugToolbarExtension()debugtoolbar.init_app(app=app)#   cache
#     cache有底层源码错误
#     解决办法  鼠标防到Cache上  ctrl + B  点击jinja2ext.py
#     进入之后 观察倒包   有一个叫做 flask.ext.cache的修改为flask_cache
#     from flask.ext.cache import make_template_fragment_key===>
#     from flask_cache import make_template_fragment_key
#     cache = Cache(config={'CACHE_TYPE':'redis'})cache.init_app(app=app)models.py
from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()setting.py
def get_database_uri(DATABASE):dialect = DATABASE.get('dialect')driver = DATABASE.get('driver')username = DATABASE.get('username')password = DATABASE.get('password')host = DATABASE.get('host')port = DATABASE.get('port')database = DATABASE.get('database')return '{}+{}://{}:{}@{}:{}/{}'.format(dialect,driver,username,password,host,port,database)class Config():Test = FalseDebug = FalseSQLALCHEMY_TRACK_MODIFICATIONS = Falseclass DevelopConfig(Config):Debug = TrueDATABASE={'dialect':'mysql','driver':'pymysql','username':'root','password':'1234','host':'localhost','port':'3306','database':'flaskday05',}SQLALCHEMY_DATABASE_URI=get_database_uri(DATABASE)ENV_NAME={'develop':DevelopConfig
}views.py
from flask import Blueprint, request, render_template, current_app,gfrom App.ext import cacheblue = Blueprint('blue',__name__)@blue.route('/')
def hello_world():return 'Hello World!'@blue.route('/index/')
# 不能导入---》 因为在init方法中
# 能导入-循环导入问题---》
# view -->ext  cache
# ext  --->view blue@cache.cached(timeout=30)
def index():print('你们多少个人去看电影阿  千万不要剧透')return 'index'# 第一次访问的时候 显示  欢迎光临  第二次访问的时候  显示小爬虫快走开@blue.route('/index1/')
def index1():ip = request.remote_addr#     缓存中如果有记录 那么就证明你来过
#     get获取的意思  set设置的意思result = cache.get('ip')if result:return '小爬虫快走开'else:cache.set('ip',ip,timeout=30)return '欢迎光临'# AOP  flask中 钩子 和 django中的中间件
# AOP 面向切面编程, 面向方面编程
# 在执行某方法之前 或者之后  执行一些方法
# eg: pymysql
#      add   delete  update  select
#      coonection   cursor  execute  close
# 每执行一个都需要链接 和 关闭@blue.route('/testaop/')
def testaop():print('i am testaop')return 'ok'# 默认情况下before_request是带()的  如果我们使用aop  需要将()删除
# @blue.before_request
# def aop():
#     print('i am aop simida')@blue.route('/add/')
def add():print('i am add')return 'add'@blue.route('/delete/')
def delete():print('i am delete')return 'delete'@blue.route('/testconfig/')
def testconfig():for c in current_app.config:print(c)return render_template('testconfig.html')@blue.route('/g/')
def g():g.ip = request.remote_addrreturn 'ok'@blue.route('/testg1/')
def testg1():
#     问:怎么获取ip (不能移动ip的位置)print(g.ip)return 'ok1'testconfig.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<ul>{% for c in config %}<li>{{ c|lower }}</li>{% endfor %}
</ul>
</body>
</html>

李晶Day05FZFlask:

flask-restful实现步骤

  1 pip install flask-restful2 在ext中 创建api对象  并且初始化  指定资源api = Api()api.init_app(app=app)api.add_resource(资源的类,路由路径)  eg:api.add_resource(Hello,'/hello/')3 注册资源在apis模块中  创建一个类class Hello(Resource):def get(self):data={}return datadef post(self):data={}return datadef delete/put/patch(self):data={}return datarestful最重要的就是返回值

作业:

1 整理本周内容 复习

2 登录页面添加验证码

3 注册页面当输入邮箱的时候 会往邮箱发送件 在邮箱激活之后 才会可以登录

__init__.py
from flask import Flaskfrom App import settings
from App.ext import init_extdef create_app():app = Flask(__name__)# session# app.config['SECRET_KEY']='114'# app.config['SESSION_TYPE']='redis'# Session(app=app)# 建立与settings文件的关键# settings.ENV_NAME.get('develop')获取的是settings文件中的value值# app.config.from_object(DevelopConfig)将类加载过来app.config.from_object(settings.ENV_NAME.get('develop'))# sqlalchemy# db.init_app(app=app)init_ext(app)return appapis.py
# apis和views是一样的
from flask_restful import Resourceclass Hello(Resource):def get(self):data = {'msg':'get'}return datadef post(self):data = {'msg': 'post'}return dataext.py
# 用来存放第三方扩展库
from flask_restful import Api
from flask_session import Sessionfrom App.apis import Hello
from App.models import dbdef init_ext(app):app.config['SECRET_KEY']='114'app.config['SESSION_TYPE']='redis'Session(app=app)db.init_app(app=app)# restfulapi = Api()api.add_resource(Hello,'/hello/')api.init_app(app=app)views.py
from flask import Blueprintblue = Blueprint('blue',__name__)@blue.route('/')
def index():return 'index'

FzFlask1:

__init__.py
from flask import Flaskfrom App import settings
from App.ext import init_extdef create_app(envname):app = Flask(__name__)app.config.from_object(settings.ENV_NAME.get(envname))init_ext(app)return appext.py'''
flask-script
flask-blueprint
flask-session
flask-sqlalchemy
'''
from flask_migrate import Migrate
from flask_session import Sessionfrom App.models import dbdef init_ext(app):# sessionapp.config['SECRET_KEY']='10010'app.config['SESSION_TYPE']='redis'Session(app=app)# sqlalchemydb.init_app(app=app)# migratemigrate = Migrate()# 注意参数的个数migrate.init_app(app=app,db=db)views.pyfrom flask import Blueprint, request
from flask.json import jsonifyfrom App.models import User, dbblue = Blueprint('blue',__name__)@blue.route('/index/')
def index():return 'index'@blue.route('/getjson/')
def getjson():data = {'resultCode':'200','resultValue':'封神演义',}# 注意flask中视图函数 不允许直接返回json  因为视图函数返回的是应该是 字符传 元祖  response实例# flask.json是flask的子类return jsonify(data)# 在后端 定义一个列表  注意列表中的数据是python中基础数据类型
@blue.route('/getscore/')
def getscore():score_list = [4,6,3,7,9,10]data = {'status':200,'score_list':score_list}return jsonify(data)@blue.route('/adduser/',methods=['get','post'])
def adduser():name = request.form.get('name')age = request.form.get('age')user = User()user.name = nameuser.age = agedb.session.add(user)db.session.commit()data = {'msg':'success'}return jsonify(data)# 通过请求方式执行不同的代码  并且返回的是json数据
@blue.route('/user/',methods=['GET','POST','DELETE','PUT','PATCH'])
def user():data = {'msg':'ok'}if request.method == 'GET':print('111111111111111')data['msg'] = 'get'return jsonify(data)elif request.method == 'POST':data['msg'] = 'post'return jsonify(data)elif request.method == 'DELETE':data['msg'] = 'delete'return jsonify(data)elif request.method == 'PUT':data['msg'] = 'put'return jsonify(data)elif request.method == 'PATCH':data['msg'] = 'patch'return jsonify(data)return jsonify(data)manager.py
from flask_migrate import MigrateCommand
from flask_script import Managerfrom App import create_app
from App.views import blueapp = create_app('develop')manager = Manager(app=app)manager.add_command('db',MigrateCommand)app.register_blueprint(blueprint=blue)if __name__ == '__main__':manager.run()json:一种轻量级的数据交换标准物物交换
货币:贝壳  通过贝壳来买卖人民币python对象==》json《=== js对象json/xmlxml可扩展的标记语言
<python1901></python1901>
常用于java语言json解析速度快  存储文档小html 超文本标记语言
文本标记语言  简单标签   超级文本标记语言(图片 视频  音频。。。)浏览器小名   html解析器http://127.0.0.1:5000/user/add
http://127.0.0.1:5000/user/delete
http://127.0.0.1:5000/user/update
http://127.0.0.1:5000/user/selectrest  通过请求的提交方式不同 然后去执行对象方法
http://127.0.0.1:5000/user请求提交方式  get    查询post   添加delete 删除put    修改    全部数据修改patch  修改    部分数据修改addUser.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript" src="/static/js/jquery.js"></script><script type="text/javascript">$(function(){$('button').click(function () {var name = $('#name').val();var age = $('#age').val();$.ajax({url:'/adduser/',type:'post',data:{'name':name,'age':age},dataType:'json',success:function (data) {console.log(data);}})})})</script>
</head>
<body>name:<input type="text" id="name"><br>age:<input type="text" id="age"><br><button>提交</button>
</body>
</html>scoreList.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="http://code.jquery.com/jquery-2.1.1.min.js"></script><script type="text/javascript">$(function () {$('#b').click(function () {$.getJSON('/getscore/',function (data) {//{#不能通过data.get获取数据 并且注释还有问题 需要删除 #}//{#score_list = data.get('score_list');#}//score_list = data['score_list']score_list = data.score_list;$ul = $('ul');for(var i=0; i<score_list.length;i++){score = score_list[i];$li = $('<li></li>');$li.html(score);$ul.append($li);}})})})</script></head>
<body><button id="b">点我</button><ul></ul>
</body>
</html>

Day06

1.验证码

def get_code(request):# 初始化画布,初始化画笔mode = "RGB"size = (200, 100)red = get_color()green = get_color()blue = get_color()color_bg = (red, green, blue)image = Image.new(mode=mode, size=size, color=color_bg)imagedraw = ImageDraw(image, mode=mode)imagefont = ImageFont.truetype(settings.FONT_PATH, 100)verify_code = generate_code()request.session['verify_code'] = verify_codefor i in range(4):fill = (get_color(), get_color(), get_color())imagedraw.text(xy=(50*i, 0), text=verify_code[i], font=imagefont, fill=fill)for i in range(100):fill = (get_color(), get_color(), get_color())xy = (random.randrange(201), random.randrange(100))imagedraw.point(xy=xy, fill=fill)fp = BytesIO()image.save(fp, "png")return HttpResponse(fp.getvalue(), content_type="image/png")import randomdef get_color():return random.randrange(256)def generate_code():source = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"code = ""for i in range(4):code += random.choice(source)return code

2.发送邮件

1 前后端分离 源码 restful

2 restful的结构化输出 2种输出

3 restful输入

4 注册 前端验证 js 验证

    后端验证 用户名字是否存在 鼠标失去焦点  ajax邮箱验证提交表单 向邮箱发送邮件  打开邮箱  点击激活链接  将状态变成激活状态邮件的生存时间画一个页面学生姓名   后台验证  前台验证学生性别学生年龄学生密码确认密码   前台密码确认验证邮箱地址   发送邮件激活状态   邮件的生存时间邮箱激活:flask-mail1 设置邮箱的授权码点击设置 然后 选择pop3  设置授权码2 注意 授权码和密码不能一致3 pip install flask-mail4 mail = Mail()5 mail.init_app(app=app)6 在settings中写 MAIL_SERVER MAIL_USERNAME  MAIL_PASSWORD7 在apis中 msg = Message(subject sender recipients注意列表)8 msg.html = 字符串 render_templates9 mail.send(msg)作业:邮件的内容尊敬的zslsww5您好:

请点击链接进行激活激活

http://127.0.0.1:8000/axf/doactive/?name=zslsww5

            点击激活  修改active的状态

5 登录 验证码 先验证验证码 减少数据库io操作

6 celery

day06代码:

apis文件包

Cat1Apis.py
from flask_restful import Resourceclass Cat1Resource(Resource):def get(self):return 'i am ok'Cat2Apis.py
from flask_restful import Resourceclass Cat2Resource(Resource):def get(self):return 'i am ok1'Cat3Apis.py
from flask_restful import Resource, marshal_with, fieldsclass Cat3Resource(Resource):'''- 默认返回的数据如果在预定义结构中不存在,数据会被自动过滤- 如果返回的数据在预定义的结构中存在,数据会正常返回- 如果返回的数据比预定义结构中的字段少,预定义的字段会呈现一个默认值如果类型是Integer  那么默认值是  0如果类型是String  那么默认值是null'''r1fields={# fields后面的类型 可以加() 可以不加()'msg':fields.String(),# 'resultCode':fields.Integer,# 'resultValue':fields.String# 'status':fields.String'resultValue':fields.String(default='dddd'),'status':fields.String(attribute='xxx')}# 结构化输出:按照指定的格式输出数据@marshal_with(r1fields)def get(self):data = {'msg':'ok','status':'200','xxx':'xxx',}return dataCat4Apis.py
from flask_restful import Resource, fields, marshalr4fields = {'msg': fields.String(),'resultCode': fields.Integer,
}class Cat4Resource(Resource):def get(self):data = {'msg':'ok','status':'200'}return marshal(data=data,fields=r4fields)Cat5Apis.py
from flask_restful import Resource, marshal_with, fieldsfrom App.models import Catcatfields = {'id':fields.Integer,'name':fields.String,'color':fields.String
}r5fields = {'msg':fields.String,'cat':fields.Nested(catfields)
}class Cat5Resource(Resource):@marshal_with(r5fields)def get(self):cat = Cat.query.first()data = {'msg':'ok','cat':cat}return dataCat6Apis.py
from flask_restful import Resource, marshal, fieldsfrom App.models import Catcatfields = {'id':fields.Integer,'name':fields.String,'color':fields.String,
}r6fields = {'msg':fields.String,'cats':fields.List(fields.Nested(catfields))
}class Cat6Resource(Resource):def get(self):cats = Cat.query.all()data = {'msg':'ok','cats':cats}return marshal(data=data,fields=r6fields)CatApis.py
from flask_restful import Resourceclass CatResource(Resource):def get(self):return {'msg':'ok'}DogApis.py
from flask_restful import Resource, reqparse# 输入
# 1 获取parser对象  eg:parser = reqparser.RequestParser()
# 2 将参数绑定到parser上 eg:parser.add_argument(name,type,help,required)
#   name 参数的名字  type 参数的类型  help如果没有参数的提示  required必须书写
# 3 将parser里的参数进行解析 解析之后为parse对象 eg  parse = parser.parse_args()
# 4 可以通过parse对象的get方法获取参数值parser = reqparse.RequestParser()parser.add_argument(name='name',type=str,help='请输入用户名字',required=True)
parser.add_argument(name='age',type=int,help='请输入年龄',required=True)
parser.add_argument(name='color',type=str,help='请输入颜色',required=True)class DogResource(Resource):# 获取 name   然后如果用户名字为空  那么提示 用户名字不可以为空# 获取年龄     然后如果年龄为空  那么提示 年龄不可以为空# 获取颜色     然后如果颜色为空  那么提示  颜色不可以为空def post(self):parse = parser.parse_args()name = parse.get('name')age = parse.get('age')color = parse.get('color')print(name,age,color)return 'i am ok'StudentApis.py
from flask import request
from flask_mail import Message
from flask_restful import Resourcefrom App.ext import mail
from App.models import Student, dbclass StudentResource(Resource):# 前端验证 如果 符合要求  那么显示绿色字体  如果不符合要求 那么显示红色字体def post(self):# name = request.form.get('name')#### students = Student.query.filter(Student.name == name)## data = {#     'msg':'用户名字可以注册',#     'status':'200',# }## if students.count() > 0:#     student = students.first()#     data['status'] = 422#     data['msg'] = '用户已经存在'#     return data# return dataname = request.form.get('name')gender = request.form.get('gender')age = request.form.get('age')password = request.form.get('password')email = request.form.get('email')student = Student()student.name = namestudent.gender = genderstudent.age = agestudent.password = passwordstudent.email = emaildb.session.add(student)db.session.commit()# 参数有三个  subject 主题  sender 发送者  recipients接受者msg = Message(subject='激活',sender='yulin_ljing@163.com',recipients=[email])msg.html = "<h1>testingxxxx</h1>"mail.send(msg)return {'msg':'ok'}__init__.py
from flask_restful import Resource, Api#
# api = Api()
#
#
# def init_urls(app):
#     api.init_app(app=app)register.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript" src="/static/js/jquery.js"></script><script type="text/javascript">$(function () {/**$('#name').blur(function () {* 前端验证var name = $(this).val();var reg = /^[a-z]{3,6}$/;//reg的test方法 是判断某字符串是否满足 某正则//如果满足返回true  没有满足返回的是falseif(reg.test(name)){$('#nameinfo').css('color','green');}else{$('#nameinfo').css('color','red');}//后台验证var name = $(this).val();$.ajax({url:'/student/',type:'post',data:{'name':name},dataType:'json',success:function (data) {var status = data['status']if(status === 422){$('#nameinfo').html(data['msg']);}else{$('#nameinfo').html(data['msg']);}}})});*/$('#sub').click(function () {var name = $('#name').val();var gender = $('#gender').val();var age = $('#age').val();var password = $('#password').val();var email = $('#email').val();$.ajax({url:'/student/',type:'post',data:{'name':name,'gender':gender,'age':age,'password':password,'email':email},dataType:'json',success:function (data) {console.log(data);}})})})</script>
</head>
<body>
<!--{#    学生姓名   后台验证  前台验证
{#                学生性别
{#                学生年龄
{#                学生密码
{#                确认密码   前台密码确认验证
{#                邮箱地址   发送邮件
{#                激活状态   邮件的生存时间#}
-->name&nbsp;&nbsp;:<input type="text" id="name">
<span id="nameinfo">请输入3到6个英文字母</span>
<br/>
gender:<input type="text" id="gender"><br/>
age&nbsp;&nbsp;&nbsp;:<input type="text" id="age"><br/>
passwd:<input type="password" id="password"><br/>
confirm:<input type="password" id="confirmpassword"><br/>
email:<input type="text" id="email"><br/>
<input type="button" value="提交" id="sub"></body>
</html>__init__.py
from flask import Flaskfrom App import settings
from App.ext import init_ext
from App.urls import init_urlsdef create_app(envname):app = Flask(__name__)app.config['JSON_AS_ASCII'] = Falseapp.config.from_object(settings.ENV_NAME.get(envname))init_ext(app)init_urls(app)return appext.py
# flask-script   flask-blueprint  flask-session  flask-sqlalchemy
# flask-migrate  flask-boostrap  flask-debugtoolbar  flask-cache
# flask-restful
from flask_bootstrap import Bootstrap
from flask_cache import Cache
from flask_debugtoolbar import DebugToolbarExtension
from flask_mail import Mail
from flask_migrate import Migrate
from flask_session import Sessionfrom App.models import db
from App.views import bluecache = Cache(config={'CACHE_TYPE':'redis'})
mail = Mail()def init_ext(app):app.register_blueprint(blueprint=blue)# flask-sessionapp.config['SECRET_KEY']='110'app.config['SESSION_TYPE']='redis'session = Session()session.init_app(app=app)#     flasksqlalchemydb.init_app(app=app)#   flask-migrate
#     python manager.py db init
#     python manager.py db migrate
#     python manager.py db upgrade
#     python manager.py db downgrademigrate = Migrate()migrate.init_app(db=db,app=app)# flask-bootstrapbootstrap = Bootstrap()bootstrap.init_app(app=app)# flask-debugtoolbarapp.debug = Truedebugtoolbar = DebugToolbarExtension()debugtoolbar.init_app(app=app)# flask-cache# cache = Cache(config={'CACHE_TYPE': 'redis'})cache.init_app(app=app)#     flask-mailmail.init_app(app=app)models.py
from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()class User(db.Model):id = db.Column(db.Integer,primary_key=True,autoincrement=True)name = db.Column(db.String(32))def to_dict(self):return {'id':self.id,'name':self.name}class Cat(db.Model):id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(32))color = db.Column(db.String(16))class Dog(db.Model):id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(32))age = db.Column(db.Integer)color = db.Column(db.String(16))
'''
学生姓名   后台验证  前台验证学生性别学生年龄学生密码确认密码   前台密码确认验证邮箱地址   发送邮件激活状态   邮件的生存时间'''class Student(db.Model):id = db.Column(db.Integer,primary_key=True,autoincrement=True)name = db.Column(db.String(32),unique=True)gender = db.Column(db.String(16),default='1')age = db.Column(db.Integer)password = db.Column(db.String(256))email = db.Column(db.String(64))active = db.Column(db.Boolean,default=False)settings.py
def get_database_uri(DATABASE):dialect = DATABASE.get('dialect')driver = DATABASE.get('driver')username = DATABASE.get('username')password = DATABASE.get('password')host = DATABASE.get('host')port = DATABASE.get('port')database = DATABASE.get('database')return '{}+{}://{}:{}@{}:{}/{}'.format(dialect,driver,username,password,host,port,database)class Config():Test = FalseDebug = FalseSQLALCHEMY_TRACK_MODIFICATIONS = FalseMAIL_SERVER = 'smtp.163.com'MAIL_USERNAME = 'yulin_ljing@163.com'MAIL_PASSWORD = 'lijing0501115'class DevelopConfig(Config):Debug = TrueDATABASE = {'dialect':'mysql','driver':'pymysql','username':'root','password':'1234','host':'localhost','port':'3306','database':'finalflask'}SQLALCHEMY_DATABASE_URI = get_database_uri(DATABASE)ENV_NAME = {'develop':DevelopConfig
}urls.py
from flask_restful import Apifrom App.apis.Cat1Apis import Cat1Resource
from App.apis.Cat2Apis import Cat2Resource
from App.apis.Cat3Apis import Cat3Resource
from App.apis.Cat4Apis import Cat4Resource
from App.apis.Cat5Apis import Cat5Resource
from App.apis.Cat6Api import Cat6Resource
from App.apis.CatApis import CatResource
from App.apis.DogApis import DogResource
from App.apis.StudentApis import StudentResourceapi = Api()def init_urls(app):api.init_app(app=app)api.add_resource(CatResource,'/cat/')
api.add_resource(Cat1Resource,'/cat1/')
api.add_resource(Cat2Resource,'/cat2/')
api.add_resource(Cat3Resource,'/cat3/')
api.add_resource(Cat4Resource,'/cat4/')
api.add_resource(Cat5Resource,'/cat5/')
api.add_resource(Cat6Resource,'/cat6/')api.add_resource(DogResource,'/dog/')api.add_resource(StudentResource,'/student/')views.py
from flask import Blueprint, jsonifyfrom App.models import Userblue = Blueprint('blue',__name__)@blue.route('/index/')
def index():return 'index'@blue.route('/getuser/')
def getuser():# 视图函数返回的是json数据 那么数据中 不可以直接返回自定义类型的对象的# 可以直接返回python自带的数据类型对象user = User.query.first()# user = [1,2,3]data = {'msg':'ok','user':user.to_dict(),}return jsonify(data)@blue.route('/getusers/')
def getusers():users = User.query.all()user_list = []for user in users:user_list.append(user.to_dict())data = {'msg':'ok','users':user_list}return jsonify(data)manager.py
from flask_migrate import MigrateCommand
from flask_script import Managerfrom App import create_appapp = create_app('develop')manager = Manager(app=app)manager.add_command('db',MigrateCommand)if __name__ == '__main__':manager.run()

Flask中的其他控件相关推荐

  1. Gridview导出到Excel,Gridview中的各类控件,Gridview中删除记录的处理

    Asp.net 2.0中新增的gridview控件,是十分强大的数据展示控件,在前面的系列文章里,分别展示了其中很多的基本用法和技巧(详见< ASP.NET 2.0中Gridview控件高级技巧 ...

  2. ASP.NET中 Calendar(日期控件)的使用

    ylbtech-ASP.NET-Control-Basic:Calendar(日期控件)的使用 ASP.NET中 Calendar(日期控件)的使用. 1.A,运行效果返回顶部 Calendar(日期 ...

  3. 在WPF中使用WinForm控件方法

    在WPF中使用WinForm控件方法 原文:在WPF中使用WinForm控件方法 1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,Syste ...

  4. 关于从页面中获取用户控件中的其它控件(如DropDownList)事件的方法

    在项目中经常把一些经常使用的代码做成用户控件以提高代码的可重用性, 一个经常遇到的就是在页面中调用用户控件中的服务器控件的事件,下面给出简单的代码示列. 我们在一个用户控件(MaterialRepor ...

  5. 在 .NET Compact Framework 2.0 中宿主 ActiveX 控件

    适用于: ActiveX Microsoft .NET Compact Framework 版本 2.0 摘要:了解如何在使用 .NET Compact 的应用程序中宿主 ActiveX 控件.本文提 ...

  6. 在 ASP.NET MVC 中使用 Chart 控件

    在 .NET 3.5 的时候,微软就提供了一个 Chart 控件,网络上有大量的关于在 VS2008 中使用这个控件的文章,在 VS2010 中,这个控件已经被集成到 ASP.NET 4.0 中,可以 ...

  7. 怎么向tab control中加其它控件(如文本框等)

    1.首先创建一个MFC对话框框架,在对话框资源上从工具箱中添加上一个Tab   Control   控件,根据需要修改一下属性,然后右击控件,为这个控件添加一个变量,将此控件跟一个CTabCtrl类变 ...

  8. C#中组件与控件的主要区别是什么?

    C#中组件与控件的主要区别是什么? 答:组件是指可重复使用并且可以和其他对象进行交互的对象.组件(component)是靠类实现的.控件(Control)是能够提供用户界面接口(UI)功能的组件.换句 ...

  9. 在WinForm应用程序中嵌入WPF控件(转)

      我们知道,在WPF界面上添加WinForm的控件需要使用WindowsFormHost类.而在WinForm界面上添加WPF控件该如何做呢?有没有类似的类呢?明显是有的,ElementHost就是 ...

最新文章

  1. quartus编译错误不支持芯片_介绍一下如何重新编译Arduino 16U2 的Firmware
  2. 东北黑土区不同纬度农田土壤真菌分子生态网络的比较
  3. antdesign 所兼容的浏览器_Edge 87.0最新离线稳定版浏览器
  4. First iOS App_Troubleshooting and Reviewing the Code
  5. 2.12日递推专题第一题
  6. 泰安第一中学2021年高考成绩查询,等级考第一天结束 泰安部分考生已完成2021年高考...
  7. python 获取当前时间再往前几个月_Python 中的时间和日期操作
  8. CentOS Linux 7绑定静态IP方法
  9. java 单例模式_谈谈Java中的单例模式
  10. FCPX字幕插件、转场插件、效果插件、MG动画、调色插件、AE模板、AE插件、PR插件
  11. 台式网卡计算机,台式机万能网卡驱动,教您如何给台式机安装万能网卡驱动
  12. 解决QQ或TIM下载群文件网路失败或者网速贼慢的办法
  13. hcia是什么等级的证书_华为hcia是什么等级的证书
  14. openssl 生成csr_如何使用OpenSSL生成证书签名请求(CSR)?
  15. 绝知此事要躬行|fatal: not in a git directoryError: Command failed with exit 128: git
  16. 计算机组成原理区分正负数实验,计算机组成原理实验报告(4个).doc
  17. 机器人焊钳选型_焊接机器人选型资料
  18. Spring @Value(#{})和@Value(${})
  19. 最小二乘法的对偶形式(CVX)
  20. 多目标蚁群算法路径规划(一)-----从数据设计到毕业论文系列

热门文章

  1. 边缘智能:边缘计算与人工智能融合的新范式
  2. 2022年计算机四级考试每日综合练习题及答案
  3. 知识库问答系统(KBQA)初探
  4. EI检索 SCI检索征稿启事
  5. php利用socket_pair进程通信,nginx 进程间通信-socketpair
  6. Windows XP 注册表优化方案
  7. 数据可视化——力导向图的绘制
  8. 《步步为营》 封装 Win7 教程 - 第一节
  9. 搞懂MOS管的米勒效应
  10. 来食路 - 素食系列之怎么挑选时令好蔬果