当前位置:   article > 正文

flask基础_flask 前端获取后端数据 json

flask 前端获取后端数据 json

一、flask安装和配置:

1、后端

服务器+wsgi+框架程序,flask是框架程序

2、前端

手机APP、浏览器、程序(爬虫)、urlliburllib2ajax

3、框架的核心

实现路由和视图(业务逻辑处理);

4、优势

dingo是重量级框架,提供了很多工具和组件,对后期扩展不友好;

5、flask的核心

werkzeugjinja2jinja2可以换)

6、flask扩展包:

Flask-SQLalchemy:操作数据库;
Flask-migrate:管理迁移数据库;
Flask-Mail:邮件;
Flask-WTF:表单;
Flask-script:插入脚本;
Flask-Login:认证用户状态;
Flask-RESTful:开发REST API的工具;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和时间;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

7、虚拟环境:

cd ~/ :切换到家目录:
ls -l: 
ls -a:
cd .virtualenv: 
ls: 所有的虚拟环境
cd flask_py2: 切换至某个虚拟环境
cd bin:可执行的二进制文件;
cd ..:返回上级目录;
cd lib:所有的安装包;
cd site-packages:可以修改第三方包中的源文件
pip list :查看当前虚拟环境中安装了哪些包
mkvirtualenv shop -p python3:创建虚拟环境shop,并指定python版本
安装python包时加sudo,安装到系统环境中,并非虚拟环境中;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

二、app对象的初始化和配置:

1、对象的初始化

  • __name__表示当前文件名字,如果这个文件为启动文件的话,__name____main__
  • app=Flask(__name__)表示以当前文件所在的目录为根目录,flask以这个模块所在的目录为根目录,默认以根目录下的static作为静态目录,以根目录下的templates作为模板目录,如果flask传的参数没有被找到,比如app=Flask('idbbkdsbkjabs')flask会以当前文件为根目录
  • Flask()的初始化参数:
import_name: 
static_url_path: 访问静态资源的默认名称,把在浏览器中访问的static换掉(120.0.0.1:5000/static/index.html换成120.0.0.1:5000/static1/index.html)
static_folder: 静态文件的目录,默认‘static’
template_folder: 模板文件的目录,默认‘templates’
  • 1
  • 2
  • 3
  • 4

2、app.run():

为简易的测试服务器

app.run(host='0.0.0.0',port=5000) # 既可以使用本地ip地址,又可以使用127.0.0.1访问,可以传debug
  • 1

3、配置文件:

  • 存值:
1)app.config.from_pyfile(文件名) #指定文件名字,以当前根目录下的文件名查找2)app.config.from_object(类名) # 从对象的方式导入,配置文件封装成类3)app.config['DEBUG']=True # 指直接操作config的字典对象
  • 1
  • 2
  • 3
  • 取值
(1)app.config.get('')
(2)app.config['']
(3)current_app.config['']
  • 1
  • 2
  • 3

三、视图函数的路由:

1、视图函数的路由规则:

  • app.url_map:可以查看整个flask的路由信息
   返回Map([Rule'/'(HEAD,OPTIONS,GET)->index,...])
             路由     请求方式     视图函数名称
  • 1
  • 2
  • 如果定义了两个相同的视图函数,路由也相同,则第一个会把第二个干掉
  • 一个视图函数可以添加多个路由
  • url_for:通过视图函数名称找到路由,返回的是路由地址,即url

2、url中的传参:

(1)转换器(动态路由):127.0.0.1:5000/user/123

@apiBP.route('/user/<int:user_id>', methods=['POST'])
def login(user_id):
    """ 用户登录 """
    print(user_id)
默认的类型:int/float/path(和默认的相似,但也接受斜线),不加转换器类型的话,默认为字符串
  • 1
  • 2
  • 3
  • 4
  • 5

(2)自定义转换器:

  • 定义自己的转换器:

class ReqexConverter(Werkzeuq.rounting.BaseConverter):
  def __init__(self,url_map,regex):
    # 调用父类的初始化方法
    super().init()
    # 将自己使用的正则表达式的参数保存到对象的属性中,
    flask回去使用这个属性来进行路由的正则匹配
    self.regex=regex
  def to_python(self,value):
    ''' 对regex值做更复杂的操作,传的值经过校验是正常的,则返回return中的值
    路径中的值转换到python程序中  '''
    return 处理过后的数据,即最终的mobile_id
  def to_url(self,value):
    return '15812345678'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 将自定义的转换器添加到flask应用中
app.url_map.converters['re']=ReqexConverter
  • 1
  • 案例
@apiBP.route('/user/<re(r'1[34578]\d{9}'):mobile_id>', methods=['POST'])
def login(mobile_id):
    """ 用户登录 """
    print(mobile_id)
    
@apiBP.route('/index', methods=['POST'])
def login():
    """ 用户登录 """
    url=url_for('send_sms',mobile='18611111111')
    # 相当于/send/15812345678
    print(mobile_id)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

四、request对象:

1、获取参数:
图片: https://uploader.shimo.im/f/DTyUn6XTkc5qRZxg.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDI5MTg3NDgsImciOiJHM1Jra1dZOHd5UmNHNjNwIiwiaWF0IjoxNjQyOTE4NDQ4LCJ1c2VySWQiOjEwMzE0MDk4fQ.EDGyENzCArAtfDTUIgCNTL47_RF5k-lMnvIhmLKM0XM

  • request.form:可以提取请求体中表单格式的数据:city=xxx&age=xxx&name=xxx,form表单中的参数;
  • request.data:请求体中不是表单格式的数据,如json传过来的字符串;
  • request.files['文件字段名']:返回的是文件对象
f=request.files['the_file']
f.save('/download/test001.txt')  # flask中文件特有的方法
f.read()
f.write()
  • 1
  • 2
  • 3
  • 4

五、abort函数、自定义错误,视图函数返回值:

1、abort函数的使用:

(1)视图函数中,可以使用abort(),终止视图函数执行,并将错误信息返回到前端。

  • 可以传递状态码信息,必须是标准的http状态码:abort(404)
  • 传递详细信息(需要是Respoese对象):abort(Respoese())

2、自定义异常处理:

@app.errorhandler(404)
def error(e):
    return '您请求的页面不存在了,请确认后再次访问!%s'%e
  • 1
  • 2
  • 3

3、返回值信息:

(1)可以返回一个元组,这样的元组必须是 (response, status, headers) 的形式,且至少包含一个元素。 status 值会覆盖状态代码, headers 可以是一个列表或字典,作为额外的消息标头值。如果是列表,[(‘响应头1的名称’,‘响应头1的值’),(‘响应头2的名称’,‘响应头2的值’)];

(2)使用make_response

resp = make_response('响应体')
resp.headers[“sample”] = “value”
resp.status =404 not found”
  • 1
  • 2
  • 3

(3)返回json

@apiBP.route('/index')
def index():
    data={
      'name':'wmz',
      'age':18
    }
    # json_str=json.dumps(data)
    # return json_str,200,{'Content-Type':'application/json'}
    # jsonify将字典转换为json格式数据,并修改响应头为json
    return jsonify(data)
    return jsonify(city='shanghai',age=18)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

六、cookie和session:

1、设置cookie

resp = make_response('响应体')
  • 1

默认有效期是临时cookies,浏览器关闭即失效,max_age为有效期,单位为秒

1)resp.set_cookies('Itcast','python',max_age=3600)2)resp.headers['Set-Cookies']='Itcast=python,Max-Age=3600'
  • 1
  • 2

2、操作cookies

  • 获取cookiesrequest.cookies.get('Itcast')
  • 删除cookies:设置有效期,使有效期过期
resp = make_response('删除cookies')
resp.delete_cookie('Itcast')
  • 1
  • 2

3、设置session数据

flask中session需要用到的秘钥字段

app.config['SECRET_KEY']='HAHAHHAHHAHAH'
session['name']='python'
session['age']=18
  • 1
  • 2
  • 3
  • 后端产生sessionId传给浏览器,浏览器下次再访问时,cookie中携带sessionId
  • flask把session数据保存在了cookie中,没有保存在后端服务器中;
  • 可以把session数据保存在数据库、redis、文件、程序内存中(定义一个全局变量)。

4、操作session数据

name=session.get['name']
  • 1

七、flask上下文和钩子:

1、上下文

(1)请求上下文(request context),request和session都属于请求上下文对象,处理多个请求的情况;

request={
'线程A'{'form':{'name':'zhangsan'},args:{}},
'线程B'{'form':{'name':'lisi'},args:{}}
} 
  • 1
  • 2
  • 3
  • 4

(2)应用上下文(application context),处理有多个应用的情况;

  • current_appg都属于应用上下文对象;
  • current_app:表示当前运行程序文件的程序实例;
  • g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量。一次请求之内,需要调用多个函数,就可以用g变量来定义变量。
@apiBP.route('/index')
def index():
    data={
      'name':'wmz',
      'age':18
    }
    g.username='zhangsan'
    say_hello()
def say_hello():
  username=g.username
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2、钩子

flask支持四种钩子:可以使用request方式进行处理:

  • before_first_request:在处理第一个请求前运行;
@app.before_first_request
def  handle_before_first_request():
  print('在第一次请求前运行')
  • 1
  • 2
  • 3
  • before_request:在每次请求前运行;

  • after_request(response):如果没有未处理的异常抛出,在每次请求后运行(前提是视图函数没有出现异常,必须有返回值);

  • teardown_request(response):在每次请求后运行,即使有未处理的异常抛出(不管视图函数是否有异常,都会执行,必须有返回值)。

3、flask-script

from flask-script import Manager  # 启动命令的管理类
manager=Manager(app) #创建manager的管理对象
manager.run() # 启动flask,启动了之后,可以用命令执行
  • 1
  • 2
  • 3

八、模板:

1、模板和自定义过滤器

return render_template('index.html',name='python')
  • 1

2、模板中可以进行运算

{{myList[0]+myList[1]}}
  • 1

3、默认的过滤器

(1)字符串过滤器:

safe:禁用转义;
  <p>{{ '<em>hello</em>' | safe }}</p>
 
capitalize:把变量值的首字母转成大写,其余字母转小写;
  <p>{{ 'hello' | capitalize }}</p>
 
lower:把值转成小写;
  <p>{{ 'HELLO' | lower }}</p>
 
upper:把值转成大写;
  <p>{{ 'hello' | upper }}</p>
 
title:把值中的每个单词的首字母都转成大写;
  <p>{{ 'hello' | title }}</p>
 
trim:把值的首尾空格去掉;
  <p>{{ ' hello world ' | trim }}</p>
 
reverse:字符串反转;
  <p>{{ 'olleh' | reverse }}</p>
 
format:格式化输出;
  <p>{{ '%s is %d' | format('name',17) }}</p>
 
striptags:渲染之前把值中所有的HTML标签都删掉;
  <p>{{ '<em>hello</em>' | striptags }}</p>

支持链式使用过滤器:
<p>{{ “ hello world  “ | trim | upper }}</p>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

(2)列表过滤器

first:取第一个元素
  <p>{{ [1,2,3,4,5,6] | first }}</p>
 
last:取最后一个元素
  <p>{{ [1,2,3,4,5,6] | last }}</p>
 
length:获取列表长度
  <p>{{ [1,2,3,4,5,6] | length }}</p>
 
sum:列表求和
  <p>{{ [1,2,3,4,5,6] | sum }}</p>
 
sort:列表排序
  <p>{{ [6,2,3,1,5,4] | sort }}</p>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

4、自定义过滤器

(1)通过 add_template_filter (过滤器函数, 模板中使用的过滤器名字)

def filter_double_sort(ls):
    return ls[::2]
app.add_template_filter(filter_double_sort,'double_2')
  • 1
  • 2
  • 3

(2)通过装饰器 app.template_filter (模板中使用的装饰器名字)

@app.template_filter('db3')
def filter_double_sort(ls):
    return ls[::-3]
  • 1
  • 2
  • 3

5、处理表单

#设置csrf_token
{{ form.csrf_token() }}
{{ form.user_name.label }}
<p>{{form.user_name}}</p>
{% for msg in form.user_name.errors %}
<p>{{msg}}</p>
{% endfor %}
{{form.user_name.errors}}  # 校验失败的时候会弹出提示
验证器中:
user_name=StringField(label=u'用户名',validators=[DataRequired('这个是错误提示信息!')])
submit按钮也需要被抽像
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

6、宏

(1)模板中多次使用的内容可以被定义为宏;

  • 不带参数:
{% macro input() %}
  <input type="text"
         name="username"
         value=""
         size="30"/>
{% endmacro %}
使用:
{{ input() }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 带参数:
{% macro input2(type,value,size='30') %}
  <input type="{{type}}"
         name="username"
         value="{{value}}"
         size="{{size}}"/>
{% endmacro %}
使用:
{{ input('password','name') }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

(2)外部引用:文件名可以自定义macro.html

{% macro input() %}
    <input type="text" name="username" placeholde="Username">
    <input type="password" name="password" placeholde="Password">
    <input type="submit">
{% endmacro %}
  • 1
  • 2
  • 3
  • 4
  • 5
在其它模板文件中先导入,再调用
{% import 'macro.html' as func %}
{{func.input()}}
  • 1
  • 2
  • 3

7、模板的继承

  • 父模板:
 {% block top %}
	顶部菜单
 {% endblock top %}
 {% block content %}
 {% endblock content %}
 {% block bottom %}
		底部
 {% endblock bottom %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 子模板:
  {% extends 'base.html' %}
  {% block content %}
   需要填充的内容
  {% endblock content %}
  • 1
  • 2
  • 3
  • 4

模板继承使用时注意点:

  • 不支持多继承。
  • 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
  • 不能在一个模板文件中定义多个相同名字的block标签。
  • 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。

九、数据库扩展包:

1、创建外键:

class User(UserMixin,Base):
    """ 用户信息表 """
    __tablename__ = 'sp_user'
    userid = Column(Integer, primary_key=True)
    user_name = Column(String(24),unique=True, nullable=False)  # 用户名称
    addresses=relationship('Address',backref='user')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
class Address(Base):
    """ 收货地址 """
    __tablename__ = 'sp_address'
    addressId=Column(Integer, primary_key=True)
    userId=Column(Integer, ForeignKey('sp_user.userid'))  # 创建人id
    provinceId=Column(Integer, nullable=False)  # 省ID
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2、查询数据

方法1:通过SQLA...方式查询
db.session.query(Role).all()
方法2:通过flask-sqla...方式查询
Role.query.all()
  • 1
  • 2
  • 3
  • 4

3、条件查询

Role.query.filter(Role.name='管理员').all()
Role.query.filter_by(name='管理员').all()
  • 1
  • 2

4、关联查询

user=User.query.get(1)
user.Address  # 可以返回userID等于1的所有地址信息
address=Address.query.get(1)
address.user  #返回addressID等于1所属的人员信息
  • 1
  • 2
  • 3
  • 4

5、让查询出来的,在输出信息中的数据显示更直观

class User(UserMixin,Base):
    """ 用户信息表 """
    __tablename__ = 'sp_user'
    userid = Column(Integer, primary_key=True)
    user_name = Column(String(24),unique=True, nullable=False)  # 用户名称
    addresses=relationship('Address',backref='user')

    def __repr__(self):
      return 'User object name=%s' %self.user_name 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

6、更新操作

User.query_by(user_name ='zhou').update({'addresses':'上海'})
  • 1

十、数据库迁移包,邮件扩展包:

pip install flask-migrate
#coding=utf-8
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand
from flask_script import Shell,Manager
app = Flask(__name__)
manager = Manager(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/Flask_test'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
#第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例
migrate = Migrate(app,db) 
#manager是Flask-Script的实例,这条语句在flask-Script中添加一个db命令
manager.add_command('db',MigrateCommand)
#定义模型Role
class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    def __repr__(self):
        return 'Role:'.format(self.name)
#定义用户
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    def __repr__(self):
        return 'User:'.format(self.username)
if __name__ == '__main__':
    manager.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 创建migrations文件夹,所有迁移文件都放在里面。
python database.py db init
  • 1
  • 创建自动迁移脚本
python database.py db migrate -m 'initial migration'
  • 1
  • 更新数据库
python database.py db upgrade
  • 1
  • 查看历史版本的具体版本
python database.py db history
  • 1
  • 复制具体版本号执行回退
python database.py db downgrade 版本号
  • 1

十一、蓝图:

  • 定义蓝图时,没有默认静态文件目录,需要手动定义,template_folder='templates'
  • 模板文件的查找顺序: 先去定义app时定义的模板目录查,定义app时默认的模板目录为根目录下的templates如果没有找到,再去定义蓝图的时候定义的模板目录里找。

十二、flask部署:

  • Gunicorn(绿色独角兽)是一个Python WSGIHTTP服务器;
  • WSGI:全称是Web Server Gateway Interfaceweb服务器网关接口),它是一种规范,它是web服务器和web应用程序之间的接口。它的作用就像是桥梁,连接在web服务器和web应用框架之间;
  • uwsgi:是一种传输协议,用于定义传输信息的类型;
  • uWSGI:是实现了uwsgi协议WSGIweb服务器。
gunicorn -w 4 -b 127.0.0.1:5000 -D --access-logfile ./ Logs/ Log main:app
-D:以后台守护进程进行
--access-logfile ./ Logs/ Log:日志文件(访问的历史记录)
nginx(会保证轮着进行转发,访问每个服务的机会均等)
  • 1
  • 2
  • 3
  • 4
  • 使用nginx部署,配置nginx.conf文件。

图片:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/774286
推荐阅读
相关标签
  

闽ICP备14008679号