python之 flask 框架
创建安装虚拟环境
两种方法
第二种
# 先打开cmd 中断
# 查看virtual是否安装过
pip show virtualenv
# 安装
pip install virtualenvwrapper-win
# workon 查看虚拟环境
vorkon
# 切换虚拟环境
# workon 虚拟环境
# mkvirtualenv 创建新的虚拟环境
mkvirtualenv falsk2env
# 删除虚拟环境
#rmvirtualenv flask2env
#进入虚拟环境
workon flask2env
创建Flask 项目
专业版pychram
社区版 要手动创建
from flask import Flask, render_template, jsonifyapp = Flask(__name__)
# 路由可以多个对一个视图函数的
@app.route('/')
@app.route('/index/')
def index():# 返回值# 直接返回# return '<b>ZEN</b>'# 模板渲染# return render_template('index.html',name='123')# 返回json对象# return {'name':'Ares-Wang','Sex':'男'}# 返回json序列化return jsonify({'name':'Ares-Wang','Sex':'男'})@app.route('/')
def home():return 'ARES-ZEN'
if __name__ == '__main__':app.run(host='0.0.0.0',debug=True)
<!-- 引入css样式表 相对路径, 从根目录 -->
<!-- <link rel="stylesheet" href="../static/CSS/index.css">-->
<!-- <link rel="stylesheet" href="/static/CSS/index.css">--><link rel="stylesheet" href="{{url_for('static',filename='CSS/index.css')}}">
Flask 项目拆分
# app.py
from APP import Create_App
app = Create_App()
if __name__ == '__main__':app.run(host='0.0.0.0',debug=True)# views.py
# views.py 路径 + 视图函数
from flask import Blueprint
from .models import *
blue = Blueprint('BlueName', __name__)
@blue.route('/')
def Home():return 'SPlIT'# __init__.py
# __init__.py :初始化文件、创建Flask应用
from flask import Flask
from .views import blue
def Create_App():# 返回Flask对象app = Flask(__name__)# print(app.config)# SECRET_KEY 是对称加密的密钥,存在浏览器的# session['xxx']='123',session 通过secret_key 把123 加密存在服务器端# 同时客户端cookie中存入cookieID 也是加密的 session 设置要配置secret_key# app.config['SECRET_KEY']='ZEN'# 设置session过期时间# app.config['PERMANENT_SESSION_LIFEATIME']=datetime.timedelta# 注册蓝图 可以注册多个蓝图app.register_blueprint(blueprint=blue)return app
路由参数
@app.route(‘/xxx/converter:variable_name’)
converter:参数类型
string:接受任何没有斜杠’/'的字符串 默认参数类型
int:接受整数
float:接受浮点数
path 接受路径, 可接受斜杠(’/‘)的字符串
uuid 只能接受uuid字符串,唯一码,一种生成规则 根GUID一样的
any 可以同时指定多种路径,进行限定
@app.route(‘/student//’) 与 @app.route(‘/student/string:username/’) 一样
@app.route(‘/student/int:id/’)
def get_student(id):
student= Student.query.get(id)
@app.route(‘/student/uuid:id/’)
@app.route(‘/student/float:num/’)
@app.route(‘/student/path:path/’)
@app.route(‘/student/<any(‘男’,女)>/’)
请求方法 常见POST GET
Flask 默认支持GET,不支持POST请求的
@app.route(‘/student/’)
同时支持get 、post 请求
@app.route(‘/student/’,methods=[‘GET’, ‘POST’])
请求对象和响应对象 request response
request
服务器在接受客户端的请求后,会自动创建Request对象,有FLask框架创建,request对象不可修改
# requests 爬虫测试下面的请求对象
import requests
request = requests.get('http://127.0.0.1:5000/index/?user=123')
request = requests.post('http://127.0.0.1:5000/index/',data={'user':3456})
print(request.text)
from flask import Flask,request
@app.route('/index/>',methods=['GET', 'POST'])
def get_index():# 获取请求方式print(request.method)# url 完整请求地址 print(request.url) # http://127.0.0.1:5000/index/?user=123'# base_url 去掉get参数的urlprint(rquest.base_url) # http://127.0.0.1:5000/index/# host_url 只有主机名和端口号print(rquest.host_url) # http://127.0.0.1:5000/# remote_addr 请求的客户端地址print(request.remote_addr) #IP地址# files 文件上传print(request.files)# 用户代理, 包括浏览器和操作系统的信息 反爬用的 类似 python-requests/2.31.0print(request.user_agent)# headers 请求头print(request.headers)# headers 请求中的cookieprint(request.cookies)# 获取请求参数 get 请求,返回是字符串# request.args.get(key,defaultValue) 如果key,没有传参,可以赋默认值,print(request.args.get(key))# 返回是ImmutableMultiDict类型print(request.args)# 获取请求参数 post 请求print(request.from.get(key))#返回是ImmutableMultiDict类型print(request.from)
ImmutableMultiDict类型
Respone响应
# 导入模板渲染用的包
from flask import render_template, jsonify, make_response,Response
@app.route('/response/')
def get_Response():# 响应的几种方式# 1、返回字符串(不常用)return 'AresZEN'# 2、模板渲染(前后端分离) 在templates中创建模板 xx.html 中jinja2语法 {{}} return render_template('xx.html',param1='' , param2='')# 3、返回json数据(前后端分离)return {'name':'Ares','age':30}# jsonify() 序列号 josn=>字符串return jsonify({'name':'Ares','age':30})# 4、自定义Response对象html= render_template('xx.html',param1='' , param2='')# 返回字符串(html格式的字符串)print(html,type(html))# 导入包make_response(返回的数据,状态码)res=make_response(html,200) res = Response(html)res.set_cookie() # 设置cookie# 上面任意一个都可以return res
Redirect 重定向
@blue.route('redirect')
def make_redirect():# 重定向的几种方式# return redirect('https://www.baidu.com')# return redirect('/路由/') # 在程序中跳转# url_for():反向解析,通过视图函数名反过来找路由# url_for('蓝图名称.视图函数名') # 注意是蓝图名称 ,不是蓝图对象 blue对象 = Blueprint('BlueName蓝图名称', __name__)# ret = url_for('蓝图名称.视图函数名')# return redirect(rect)# url_for 传参ret= url_for('蓝图名称.视图函数名',参数名=Value,参数名2=Value2)return redirect(rect2)
会话技术 Cookie和Session
设置cookie
获取cookie
request.cookies.get(key)
删除cookie
response.delete_cookie(key)
cookie不能存中文
session
session服务器端会话技术,依赖于cookie
特点:
- 服务端的会话技术
- 所有数据存储在服务器中
- 默认存储在内存中
- 存储结构:key-value形式,键值对
- session 离不开cookie
- sessionID存储在客户端, session的值存在在服务端
session设置
session[‘key’]=‘value’
获取session 如果不存在,就返回 default指定的值
session.get(key,default=None)
删除session
session.pop(key) 删除某一值
session.clear() 清除所有session
cookie VS session
cookie: ①存储在客户端(浏览器)②安全性较低③可以降低服务器压力
session:①存储在服务端(服务器)②安全性高③对服务器要求较高④仍然需要依赖cookie, 服务器生成的sessionID会返回给客户端,sessionID 存储在客户端。
模板Template
JinJa2 引擎的模板语法,及传参
模板语法主要分为两种:
- 变量
- 标签
模板中的变量 {{ 变量名 }} 变量不存在,默认忽略,不会报错
views 视图函数传递给模板的数据 return render_template(‘xxx.html’,参数1=value1,参数2=Value2)或者
data ={ ‘age’ :20,‘name’:‘ZEN’ ,hobbys:[‘football’,‘basketball’]}
render_template(‘xxx.html’, **data)
模板中取值 {{ age }} {{name}}
{{ hobbys }} 返回是 [‘football’,‘basketball’] 的字符串 所以一般用for循环取值循环 for
{% for hobby in hobbys %}
# segment
{% else %} #hobby 不存在了,就进入else 了。segment
{% endfor %} 要有结束标签
使用 获取循环信息 loop
{% for hobby in hobbys %}
{{hobby}}
index:{{ loop.index }} # 从1开始的下标
index:{{ loop.index0 }} # 从0开始的下标
index:{{ loop.revindex }} # 反向下标,不包括0
index:{{ loop.revindex0 }} # 反向下标,包括0
index:{{ loop.first }} # 判断是否是第一个元素
index:{{ loop.last }} # 判断是否是最后一个元素模板中的标签 {% tag %} 注意要有结束标签 注意要有结束标签
控制逻辑、使用外部表达式 创建变量 宏定义
{% if age >=18 %}成年
模板继承
<!-- 定义Base.html 模板页 -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>ParentTemplate</title><link rel="stylesheet" href="{{ url_for('static',filename='base.css') }}"/>{% block extcss %}{% endblock %}
</head>
<body>{% block head %}{% endblock %}{% block content %}{% endblock %}{% block foot %}{% endblock %}<script src="{{ url_for('static',filename='baseJS.js') }}"></script>{% block extjs %}{% endblock %}</body>
</html>
在父模板挖坑
<!-- 定义inc.html -->
<hr>
<h4>include文件</h4>
<hr>
<!-- 定义1.html 继承模板Base.html页 -->
{% extends 'Base.html'%}{% block extcss %}<link rel="stylesheet" href="{{ url_for('static',filename='index.css') }}"/>
{% endblock %}
{% block head %}
<p>我是head标签</p>
{% endblock %}
{% block content%}{% include 'inc.html' %}<p>AAA</p>
{% endblock %}
在子模版填坑
在父模板Base.html挖坑,在子模版1.html填坑
include 包含,将其它的html包含进来
{% extends '1.html' %}
{% block content %}
{{super()}}
<p>AresZEN</p>
{% endblock %}
{# 定义 Python函数}
{% macro person(name.age) %}<b>姓名:{{ name }}, 年龄:{{ age }} </b>
{% endmarco %}{% block foot %}{{ person('ZEN',27) }}
{% endblock %}
<!-- 定义2.html 继承模板1.html页 ,1.html又继承Base.html-->
{% extends '1.html' %}{% block content %}<!-- 把父模版内容保留下来 -->{{super()}}<p>AresZEN</p>
{% endblock %}
模型基础
安装 flask_sqlalchemy (用于ORM)
pip install flask_ sqlalchemy -i https://pypi.douban.com/simple
安装 flask_migrate (用于数据迁移 把数据库模型迁移到数据库中)
pip install flask_ migrate -i https://pypi.douban.com/simple
安装 pymysql (mysql 驱动)
pip install pymysql -i https://pypi.douban.com/simple
Flask中使用ORM
连接数据库需要指定配置
数据库模型的定义
一个数据库模型对应一个数据库中的表,所有的数据库模型都要基础ORM对象的Modle基类,即db.Model
# models.py 模型 数据库
# 创建数据库模型
# 模型 =》 数据库
# 类 =》 表结构
# 类属性 =》 表字段
# 一个对象 =》 表的一个行数据
from .exts import db
class Account(db.Model):# 定义数据库的表名__tablename__ = "account"id = db.Column(db.Integer,primary_key=True, autoincrement=True)account = db.Column(db.String(10),unique=True,nullable=False)username = db.Column(db.String(30),nullable=False)# 定义显示信息 在模型类中,重写 __repr__ 方法, def __repr__(self):"""定义之后,可以让显示对象的时候更直观"""return "User object : username =%s" % self.username
# exts.py 插件管理# 1、导入第三方插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate# 2、 初始化对象
db = SQLAlchemy() # ORM
migrate = Migrate() # 数据迁移# 3、与app对象绑定
def init_exts(app):db.init_app(app=app)migrate.init_app(app=app,db=db)
?# __init__.py :初始化文件、创建Flask应用
import datetimefrom flask import Flaskfrom .views import bluefrom .exts import init_exts
def Create_App():# 返回Flask对象app = Flask(__name__)# ORM 数据库配置# SQLite 数据库连接不需要额外驱动,也不需要用用户名和密码 SQLite 一般是手机程序用的 本地数据库DB_URI='sqlite:///sqlite3.db'app.config['SQLALCHEMY_DATABASE_URI']=DB_URI # 配置连接数据库路径DB_URIapp.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False # 禁用对象追踪修改# 初始化插件init_exts(app=app)# 注册蓝图 可以注册多个蓝图app.register_blueprint(blueprint=blue)return app```
数据迁移 : 就是把model模型在数据库中创建表
- 先在cmd 或Terminal 进入项目目录(可以把选择项目 拖入到terminal)(app.py所在目录)
- 返回执行如下命令
- flask db init # 创建迁移文件夹migrates,只能执行一次
- flask db migrate # 生成迁移文件
- flask db upgrade # 执行迁移文件的升级 数据库就有表啦 如果表结构变化要执行这个 把迁移中的改动应用到数据库中
- flask db downgrade # 执行文件中的降级
配置mysql 前提 要存在这个数据库
DB_URI=’mysql+pymysql://root:root@localhost:3306/数据名‘
表的CRUD操作
要在视图函数操作数据模型,从而同步数据库
# views.py 中
# 蓝图
from flask import Blueprint,render_template,request
from .models import *# 蓝图
blue = Blueprint('bluename',__name__)
@blue.route('/')
def index():return render_template('index.html')
# 表单操作:CRUD操作
@blue.route('/accountadd/',methods=['GET','POST'])
def account_add():# 添加一个记录 Account 是类,定义在models.pyu = Account()if request.method=='GET':u.account = request.args.get('account')u.username = request.args.get('username')else:u.account = request.from.get('account')u.username = request.from.get('username') # views.py中没有导入 exts为啥油db对象,因为db对象在models.py 导入了。 因此 views中导入model,相当于也导入了extsdb.session.add(u) # 将u对象添加到session中 db.session.commit() # 同步到数据库中return 'success!'@blue.route('/accountaddall/')
def account_add():# 添加多条记录 Account 是类,定义在models.pyusers = []for i in range(1,10):u=Account()u.account = 'ZEN_'+str(i)u.username = 'Ares_'+str(i) users.append(u) # views.py中没有导入 exts为啥油db对象,因为db对象在models.py 导入了。 因此 views中导入model,相当于也导入了exts# db.session.add_all(对象列表)try:db.session.add_all(users) # 将u对象列表添加到session中 db.session.commit() # 同步到数据库中 事务提交except Exception as e:db.session.rollback() # 回滚db.session.flush() # 把session中数据清理掉 return 'fail: '+ str(e)return 'success!'@blue.route('/accountdelete/')
def account_del():try:u=Account.query.first() # 查询第一条数据db.session.delete(u)db.session.commit()except Exception as e:db.session.rollback()db.session.flush() return 'success!'@blue.route('/accountupdate/')
def account_update():try:u=Account.query.first() # 查询第一条数据u.username='yyds' db.session.commit()except Exception as e:db.session.rollback()db.session.flush() return 'success!'# 查询数据
@blue.route('/userget/')
def user_get():# all(): 以列表形式返回查询的所有结果,返回列表# users = Account.query.all()# first() 返回查询的第一个结果,如果没有结果,则返回None# user = Account.query.first() 可以继承 过滤器# filter() 把过滤器添加到原查询上,返回一个新查询,可以继续 . 过滤器# users = Account.query.filter() 可以继承 过滤器# user = Account.query.filter(Account.username=='yyds')# filter_by() 把**等值**过滤器添加到原查询上,返回一个新查询# filter_by() 与 filter() 区别# user = Account.query.filter_by(username='yyds')# count() 返回查询结果的数量# users = Account.query.filter() 可以继承 过滤器print(users.count())# first_or_404() 返回查询的第一个结果,如果没有结果,则终止请求,返回404错误响应# user = Account.query.filter_by(username='yyds').first_or_404()# get() 返回指定主键对应的行,如果没有对应的行,则返回None ,此处家人username是主键# user = Account.query.get(username='yyds')# get_or_404() 返回指定主键对应的行,如果没有找到指定的主键,则终止请求,返回404错误响应#user = Account.query.get(username='yyds')# limit() 取前面几条 使用指定的值限制原查询返回的结果数量,返回一个新查询 可以继承 过滤器# offset() 跳过前几条 偏移原查询返回的结果,返回一个新查询 ,可以继承 过滤器# users = Account.query.offset(3).limit(4)# order_by() 排序 升序# users = Account.query.order_by('id')# order_by() 排序 降序 需要到包 from sqlalchemy import desc# users = Account.query.order_by(desc('id'))# 逻辑运算符 and_ , or_ , not_users = Account.query.filter(Account.username='yyds' , Account.id < 100) # 且 默认# 需要到包 from sqlalchemy import and_ , or_ , not_users = Account.query.filter(and_(Account.username='yyds', Account.id < 100) # 且# 查询属性# contains 模糊查询 类似 sql likeusers = Account.query.filter(Account.username.contains('yd'))# in_() 其中只有 类似 sql inusers = Account.query.filter(Account.username.in_(['yyds','jjz']))# startswith(): 以某字符串开头# endswith(): 以某字符串结尾users = Account.query.filter(Account.username.startswith('yy'))# __gt__ 大于# __ge__ 大于等于# __lt__ 小于# __le__ 小于等于users = Account.query.filter(Account.id.__gt__(300))return 'success!'
分页
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<ul>{% for item in Accounts %}<li>{{ item.username }}</li>{% endfor %}
</ul>
</body>
</html>
@blue.route('/paginate/')
def get_info():page = int(request.args.get('page', 1))per_page = int(request.args.get('per_page', 5))Accounts = Account.query.paginate(page=page,per_page=per_page).itemsreturn render_template('info.html', Accounts)
多表关联
## model.py 一对多 案例
# models.py 模型 :和数据库相关的
from .exts import db
"""department :employee =》 1:N 1对多
外键要设置在 N: 多的 一个表
"""
# 创建 department 部门表 即 Department 模型
# 模型需要继承db.Model,否则就普通的类
class Department(db.Model):# 表名__tablename__ = 'department'id = db.Column(db.Integer, primary_key=True, autoincrement=True)# 部门编号deptCode = db.Column(db.String(30), nullable=False)# 建立关联# 第一个参数:关联的模型名,因python语言是解释性语言,Employees, 需要需要 用 ''# 第二个参数:反向引用的名称,department 对象# 让employee去反过来得到department对象的名称 employee.department 是个department对象# 第三个参数: 延迟加载,懒加载, 用到的时候,才会建立关系,懒加载:为了提高性能,节约资源# 这里departments不是字段,不是字段 是类的属性employees = db.relationship('Employees', backref='department', lazy=True)"""查询员工所属的部门,反向引用departmentemp = Employee.query.get('emp_Code值')# department 要跟 backref对应的值保持一致 # emp.department 返回是department对象dept = emp.department code=dept.deptCode 查询某部门下面的所有员工dept = Department.query.get('deptCode值')dept.employees # 所有部门编码下的员工信息 返回是employee 对象列表"""
# 创建employee 员工表 即 Employee 模型
# 模型需要继承db.Model,否则就普通的类
class Employee(db.Model):# 表名__tablename__ = 'employee'id = db.Column(db.Integer, autoincrement=True)# 员工姓名emp_name = db.Column(db.String(30), nullable=False)# 员工编号emp_Code = db.Column(db.String(30),nullable=False, unique=True, primary_key=True)# 外键 也是字段, 跟 员工表的 员工编号关联 1:N 外键也放在N的表中# 实现一对多关系,要在对应的表 添加 db.relationshipdepartment = db.Column(db.String(30),db.ForeignKey(Department.deptCode), nullable=False, unique=True)
多对多关系表 N:M
N:M 多对多关系,还存在两个表的中间表:关联作用
# models.py
from .ext import db
# usermodel 和 usermodel 建立关联表
collect = db.Table(# 表名'collects',# 组合主键# 字段db.Column('user_id',db.Integer,db.ForeignKey('usermodel.id'),primary_key=True)db.Column('sysmodel_id',db.Integer,db.ForeignKey('sysmodel.id'),primary_key=True)
)
# 用户表
Class UserModel(db.Model):__tablename__='usermodel'# 字段id = db.Column(db.Integer,primary_key=True,autoincrement=True)username = db.Column(db,String(30))userCode = db.Column(db.String(30),)
# 系统模块
Class SysModel(db.Model):__tablename__:'sysmodel'id = db.Column(db.Integer,primary_key=True,autoincrement=True)name = db.Column(db.String(30))# 关联# secondary=collect: 设置中间表users =db.relationship('UserModel',backref='sysmodels',lazy=True,secondary=collect)
# views.py
"""
用户表和系统模块表 追加数据略
"""
@blue.route('/addcollect/')
def add_collect():# 用户拥有的系统模块user = UserModel.query.get('key')sysmodel = SysModel.query.get('key')# user.sysmodels 是反向查询的 backref='sysmodels'user.sysmodels.append(sysmodel)db.session.commit()return 'success!'@blue.route('/getcollect/')
def get_collect():# 查询某用户拥有的系统模块user = UserModel.query.get('key')print(user.sysmodels) # 返回list# 查询系统模块拥有的用户sysmodel = SysModel.query.get('key')print(sysmodel.users) # 返回是查询集 可以继续用filter 、filter_by过滤方法print(list(sysmodel.usrs)) 返回list
@blue.route('/deluser/')
def del_user():# 多对对 关联删除是级联删除,跟1对多删除不一样, 1对多, 1的一方删除数据,多的一方 对应数据外键 nulluser = UserModel.query.get('key')db.session.delete(user)db.session.commit()# 删除用户,对应用户在中间表collect中记录也会删除。
插件管理 值 flask-caching
安装:
pip install flask-caching # 是连接符,不是下划线
# exts.py 插件管理# 1、导入第三方插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# 是下划线,不是连接符
from flask_caching import Cache
# 2、 初始化对象
db = SQLAlchemy() # ORM
migrate = Migrate() # 数据迁移
cache = Cache(config = {'CACHE_TYPE':'simple'
})
# 3、与app对象绑定
def init_exts(app):db.init_app(app=app)migrate.init_app(app=app,db=db)cache.init_app(app=app)
cache 应用
# views.py
# @ 装饰器
@blue.route('/')
@cache.cached(timeout=20) @ 开始访问(执行里面的代码),第二个方法缓存(不执行代码),缓存有效期20s,超时,会再次访问执行里面的代码
def home():print('xxx')# 模拟访问复杂的逻辑运算time.sleep(5)return 'ZEN'
钩子函数= 中间件,类似AOP框架拦截,类似Vue中的挂载点
钩子函数(中间件 MIddleware)是执行函数(视图函数)和目标函数之前挂载的函数,框架开发者给调用方提供一个point-挂载点
是一个AOP切面编程思想
常用钩子函数
- before_first_request:处理第一次请求之前执行
- before_request: 在每次请求之前执行。通常使用这个钩子函数预处理一些比哪里,实现反爬 request.user_agent等
- after_request: 注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行
- teardown_appcontext: 当app上下文被移除之后的函数,可以进行数据库的提交或者回滚
用爬虫访问 如果没有做反爬 (headers没配置 cookie、user-agent)
request.user_agent.string # python-requests/2.28.2 类似这种结果
from .exts import *
# views.py
#钩子函数不需要配置路由
@blue.before_request
def before():ip=request.remote_addr# cache.get() cache.set()if cache.get(ip):# 做了拦截,不会进入视图函数return '禁止爬虫访问!'else:# 对每个IP配置一个缓存,1秒内不让重复访问cache.set(ip,'value',timeout=1)# string 别忘记if "python" in request.user_agent.string:return "禁止用python爬虫"# @ 装饰器
@blue.route('/')
@cache.cached(timeout=20) @ 开始访问(执行里面的代码),第二个方法缓存(不执行代码),缓存有效期20s,超时,会再次访问执行里面的代码
def home():print('xxx')# 模拟访问复杂的逻辑运算time.sleep(5)return 'ZEN'
Flask 内置对象
# views.py 钩子函数
@blue.before_request
def before():# Flask内置对象# request : 请求对象# session : 会话对象# g : global 全局对象# current_app Flask应用对象g.xx = 'yyds'
默认 static、templates 跟__init__.py 是平级的, app=Flask(name)
如果不是平级 要在初始化app=Flask(name,static_folder=‘路径’,template_folder=‘路径’)
前端后端分离 值 Flask-RESTful
render_template 模板渲染 是前端和后端混在一起的
.net 中基于MVC框架的 webapi 是专门做接口的,后端的, python值flask框架提供了flask-restful包render_template 用在views.py中的,是 # 视图函数: FBV Function Based View 路由用@装饰器
类视图 : CBV Class Based View 不需要是使用后端分离的, 不需要有views.py 不用路由@装饰器
flask-restful
安装
pip install flask-restful
# exts.py 插件管理
# 1、导入第三方插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# 是下划线,不是连接符
from flask_caching import Cache
# 注意是Api
from flask_restfull import Api
# 2、 初始化对象
db = SQLAlchemy() # ORM
migrate = Migrate() # 数据迁移
cache = Cache(config = {'CACHE_TYPE':'simple'
})
api = Api()
# 3、与app对象绑定
def init_exts(app):db.init_app(app=app)migrate.init_app(app=app,db=db)cache.init_app(app=app)api.init_app(app=app)
app.py
运行前先加载__init__.py
init.py中会加载三个包
from flask import Flask
– 插件管理—
from .exts import init_exts
– 路由—
from .urls import *
在执行app.py 的Create_App(),创建flask对象, 同时给这个flask对象绑定插件
# app.py
# Create_APP 写在__init__.py 中,所以导入把 要 包名 APP
from APP import Create_App
app = Create_App()
if __name__ == '__main__':app.run(host='0.0.0.0',debug=True)
# __init__.py :初始化文件、创建Flask应用
from flask import Flask
from .exts import init_exts
from .urls import *
def Create_App():# 返回Flask对象app = Flask(__name__)# 初始化插件,创建的app应用,附加了哪些插件init_exts(app=app)return app
# exts.py 插件管理 三部曲
# 1、导入第三方插件
from flask_restful import Api
# 2、 初始化对象
api=Api()
# 3、与app对象绑定
def init_exts(app):api.init_app(app=app)
# apis.py 接口用的
from flask_restful import Resource
# 类视图 : CBV Class Based View
# 视图函数: FBV Function Based View
# 继承Resource
class StudentResource(Resource):def get(self):return '我是get 请求'def post(self):return '我是Post请求'
# urls.py 路由文件
from .exts import api
from .apis import *
# 注册路由 api.add_resource(类视图 ,路由)
api.add_resource(StudentResource,'/stu/')
字段格式化
为了定义规范接口输出数据格式,要对字段格式化
分两步:
1、fields进行定义
2、在接口用@装饰器修饰 @marshal_with(需要返回的数据格式)
说明:
如果返回的数据在预定义的结构中存在,数据会正常返回
如果返回的数据比预定义结构中字段少,预定义的字段会呈现默认值。默认值也可以设定
如果返回的数据不在预定义结构中,则数据会被自动过滤(舍弃)
# apis.py
from flask_restful import Resource,fields,marshal_with# 输出字段格式
ret_info={'name':fields.String,'age':fields.Integer,'SchoolName':fields.String,'address':fields.String
}
# 输出字段格式
ret_fields={'status':fields.Integer,'isSecces':fields.String(default='fail'),# 对方用data,其实映射是password数据的值'data':fields.String(attribute='password'),'msg':fields.String,'studentinfo':fields.Nested(ret_info)
}
# 继承Resource
class StudentResource(Resource):@marshal_with(ret_fields)def get(self):# Student是models.py 需要数据迁移stu=Student.query.first()return {'status':200,'isSecces':'ok','msg':'win','password':'123',# Student信息'studentinfo':stu}ret_fields2={'status':fields.Integer,'isSecces':fields.String(default='fail'),# 对方用data,其实映射是password数据的值'data':fields.String(attribute='password'),'msg':fields.String,'studentinfo':fields.List(fields.Nested(ret_info))
}
class StudentALLResource(Resource):@marshal_with(ret_fields2)def get(self):# Student是models.py 需要数据迁移stu=Student.query.all()return {'status':200,'isSecces':'ok','msg':'win','password':'123',# Student信息'studentinfo':stu}
"""
# 返回的结果
{"status": 200,"isSecces": "ok","data": "123","msg": "win","studentinfo":[{"name":"ZEN","age":33,"SchoolName":"家里蹲","address":"中国"}, {"name":"ZEN1","age":331,"SchoolName":"家里蹲1","address":"中国1"}]}
"""
ret_url={'name':fields.String,'url':fields.url(endpoint='id',absolute=False)
}
class urlResource(Resource):@marshal_with(ret_url)def get(self): return {'name':200,'url':'/' }
"""
# 返回的结果
{"status": 200,"isSecces": "ok","data": "123","msg": "win","studentinfo":{"name":"ZEN","age":33,"SchoolName":"家里蹲","address":"中国"}}
"""
# urls.py 路由文件
from .exts import api
from .apis import *
# 路由
api.add_resource(StudentResource,'/')
api.add_resource(urlResource,'/url/',endpoint='id')
api.add_resource(StudentALLResource,'/stuall/')
参数解析
可以不通过post : request.form 或 get : request.args 获取参数。而是通过reqparse.RequestParser 来解析
# apis.py
from flask_restful import Resource,reqparse
# 参数转换器
parser = reqparse.RequestParser()
parser.add_argument('name',type=str)
parser.add_argument('info',type=str,action='append') # 支持多个info
parser.add_argument('cookiex',type=str,location='cookies') # 获取cookies中数据
class StudentResource(Resource):def get(self):# 获取参数args=parser.parse_args()name=args.get('name')return {'key':name}
# spider.py 爬虫测试
import requestsrequest = requests.get('http://127.0.0.1:5000/',json={'name':'23','info':['123','erew']},headers={'Content-Type':'application/json'})
print(request.text)
python之 flask 框架相关推荐
- Python 使用 Flask框架记录
Python 使用 Flask框架记录 1.安装Flask Flask依赖两个外部库,Werkzeug和Jinja2,Werkzeug是一个WSGI(服务器网关接口).Jinja2时负责渲染模板. ...
- python 框架好学吗-python的flask框架难学吗
Flask框架难学吗?它和Django哪个更容易一些,这可能是学Python web开发的同学经常问的问题,下面来说一下flask框架. Flask是python的web框架,最大的特征是轻便,让开发 ...
- Python——使用Flask框架封装接口
Python--使用Flask框架封装接口 引言 Flask是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活.轻便.安全且容易上手.它可以很好地结合MVC模式进行开发,开发 ...
- python生成json接口_基于python的Flask框架写json接口并且结合eolinker进行接口测试
一.前言 很多时候为了提高软件开发的效率,后端程序人员理想状态下应该编写程序测试接口供前端程序人员进行测试,以便前端的开发.笔者由于项目的需求近期尝试学习了一下测试接口的编写,以Python+Flas ...
- python的flask框架显示柱状图_使用Python的Flask框架,结合Highchart,动态渲染图表...
服务端动态渲染图表 参考文章链接:https://www.highcharts.com.cn/docs/dynamic-produce-html-page 参考文章是使用php写的,我这边改用pyth ...
- 【python】flask框架
[python]flask框架 部分参考来源 什么是RESTful Web API(Web应用程序接口) REST RESTful RESTful api设计规范 什么是Flask 安装Flask 使 ...
- 基于Python的Flask框架实现的寻宝通关游戏 课程论文+项目源码
资源下载地址:https://download.csdn.net/download/sheziqiong/85705658 资源下载地址:https://download.csdn.net/downl ...
- python上手--flask框架web开发实践-数据库
这篇文章,由易而难,步骤清晰,思路讲得很明白.花两小时跟着作者稻谷先生的这篇文章走一遍,对学习python使用Flask来开发web的应用很有帮助. python上手--flask框架web开发实践 ...
- 基于Python的Flask框架开发的在线电影网站系统(附源码)
来源丨网络 今天给大家分享的是基于Python的Flask框架开发的在线电影网站系统. 项目介绍 项目介绍:网站前端采用HTML5编写,使用Bootstrap前端开发框架,后端使用Python3语言编 ...
最新文章
- 书评 | 9 年码龄工程师读 Android 经典
- Window7系统 中常见的进程命令分析?
- Windows下及Mac下的IntelliJ IDEA快捷键
- count函数里加函数_PHP count()函数与示例
- 服务器消息不是按顺序来的,消息队列之 RocketMQ(示例代码)
- Form Builder的三种查询方法构建
- 宏、函数、宏和函数的区别
- redis4数据类型.更新HyperLogLog类型
- StackExchange.Redis学习笔记(三) 数据库及密码配置 GetServer函数
- 使用ZbarSDK实现扫描二维码以及条形码功能(iOS)
- RHadoop协同过滤算法
- 安装vs 2015 社区版
- Word中如何输入花体数学字符
- setoolkit制作简单钓鱼网站
- 猜字游戏python程序_python 猜字游戏
- 纸壳CMS替换默认实现
- 第6章 详细设计(软件工程导论 第6版)
- MIT多变量微积分--3.矩阵,逆矩阵
- Java:抽象成类找对象
- 万向节死锁的理解与CS摄像机减少死锁的简单实现
热门文章
- GridView添加序号列
- STL、PLY、OBJ格式分析
- vivo手机支持java功能_vivo手机有哪些功能 vivo手机实用功能介绍【详解】
- 粒子群算法(PSO)初识
- C++:3类和对象、文件操作
- 油管8k视频使用av1格式 用什么显卡才行 为什么cpu 100%
- 【材料】北大深研院杨世和教授课题组JACS:碗烯铵盐对钙钛矿表面的重构助力器件光伏性能的提升...
- 马哥python 培训
- 太赫兹安检“无形检测”时代已经来临
- SpringCache的介绍和使用