Flask复习(配置数据库/ORM操作/使用原生SQL查询/HTTP请求(get/post)/详解url)
一、配置数据库信息
config.py数据库信息配置
#设置连接数据库路径 DB_URI = "mysql+pymysql://root:root@127.0.0.1:3306/bbs?charset=utf8" #msyql+pymysql://用户名:密码@数据库连接地址:端口号/数据库名 #SQLALCHEMY_DATABASE_URI加载配置好的URI SQLALCHEMY_DATABASE_URI = DB_URI #决定是否追踪对象的修改,一般设置False SQLALCHEMY_TRACK_MODIFICATIONS =False
exts.py为了解决循环调用,单独把SQLAlchemy独立成在一个文件中
from flask_sqlalchemy import SQLAlchemy #导入模块 db = SQLAlchemy()
Models.py模型类,用来生成数据库表
from exts import db #导入db模块,设置字段 class UserInfo(db.Model): #指定表名,没有就用类名做表名 __tablename__='user_info' #id设置为主键并且自动增长 id=db.Column(db.Integer,primary_key=True,autoincrement=True) username=db.Column(db.String,nullable=False)
数据迁移
使用flask_script和flask_migrate
二、ORM操作(增删改查) https://blog.****.net/weixin_42750983/article/details/82431257
1.增加数据 (flask中修改数据后需要添加事务和提交事务)
#实例化模型类作为一条记录 document = Post(author_id=user_id, title=request.form['title'], body=request.form['corpus'], created=d_time,has_edited=True) #将值对应字段传入 db.session.add(document) #把新创建的记录添加到数据库会话 db.session.commit() #提交到数据库会话 #添加多条记录使用add_all(),也可以传入单条记录,也可以传入一个列表:[document1,document2,document3] db.session.add_all([document1,document2,document3])
2.查询数据
常用过滤器(指查询条件,如果没有查询条件下面这些用不到,直接使用查询执行器)
filter(条件) 返回符合该条件的查询集,BaseQuery对象 Book.query.filter(Book.id==1) filter_by() 和filter查询一样,只是括号内的条件写法不一样 Book.query.filter_by(id=1) limit 使用指定的值限定原查询返回的结果 offset() order_by() 根据字段进行排序,默认是正序,返回新查询集,desc可以反序 Book.query.order_by(Book.id) Book.query.order_by(Book.id.desc) group_by() 根据字段进行分组,返回新查询集合
常用查询执行器
all() 以列表形式返回查询的所有结果 Book.query.filter(Book.id==1).all() first() 返回查询的第一个结果,如果未查到,返回None Book.query.filter(Book.id==1).first() get() 返回指定主键对应的行 Book.query.get(1) #写的是主键值 count() 返回查询结果的数量 Book.query.count() paginate() 返回一个Paginate对象,参数一:第几页,参数二:每页个数,参数3:如果没有该页数返回False Book.query.paginate(2,3,False)
两种查询写法
1.基于实体类来查询 #模型类.query.过滤方法函数()
2.根据db.session.query() #db.session.query(查询的数据).过滤方法函数()
db.session.query(模型类) 等价于 模型类.query db.session.query()功能更强大,可以进行多表查询
示例 参考链接:https://www.cnblogs.com/lovershowtime/p/11756891.html
all():查询全部的数据,其结果是一个列表,每一个元素都是一个对象 students = Student.query.all() order_by():查询按序排列 get(): 直接写查询条件 User.query.get(1) #用主键查询用户 过滤查询: 1.filter 查询结果是<class 'flask_sqlalchemy.BaseQuery'>,打印出来是SQL语句 studnets = Student.query.filter(Student.id==1) 2.filter_by 查询结果和filter一样 students = Student.query.filter_by(id=1) 3.原生sql查询id=1的信息 sql = 'select * from student where id=1;' students = db.session.execute(sql)
between 在什么之间
aa=session.query(Users).filter(Users.id.between(4, 7), Users.name == '李四').all()
like 通配符
ret1 = db.session.query(Users).filter(Users.name.like('李%')).all()
切片
result = db.session.query(Users)[1:3] #[<Users 2>, <Users 3>]
order_by(排序)
ret1 = session.query(Users).order_by(Users.name.desc()).all() #desc升序 asc是降序
group_by (分组)
from sqlalchemy.sql import func # 导入 func,func 中有聚合函数 ret = db.session.query( Users.dep_id, func.count(Users.id), ).group_by(Users.dep_id).all()
distinct(去重)
from sqlalchemy import distinct #导入distinct #去重后的标签名 labels=dbS.session.query(distinct(Label.label_name)).all() #去重后的标签数量 label_distinct=dbS.session.query(func.count(distinct(Label.label_name))).all()
limit(可以限制每次查询数量)
#查询10条 post=db.session.query(Post).limit(10).all()
offset(限制查找数据的时候过滤掉前面多少条)
post=db.session.query(Post).offset(10).limit(10).all()
slice(切片)
post=db.session.query(Post).slice(10,20).all()
3.修改数据
思路:获取到需要修改的对象,通过对象.属性的方式将属性重新赋值,然后使用commit提交事务
写法1:查询出需要修改对象,通过对象.属性方式修改
students = Student.query.filter_by(s_id=3).first() students.s_name = '哈哈' db.session.commit()
写法2:通过update修改
Student.query.filter_by(s_id=3).update({'s_name':'娃哈哈'}) db.session.commit()
4.删除数据
思路:查询出需要删除的对象,调用db.session.delete(记录对象)实现,然后db.session.commit()提交会话
写法1:
students = Student.query.filter_by(s_id=2).first() db.session.delete(students) db.session.commit()
写法2:
students = Student.query.filter_by(s_id=1).all() db.session.delete(students[0]) db.session.commit()
数据库查询使用原生sql:excute() ******
data = db.session.excute('SELECT id FROM user WHERE username = ?', (username,)) 使用?占位符,后面的元组参数可以代替 data.fetchone()查询返回一个记录行。如果没有查询结果,则返回None。还有fetchall(),返回所有结果的列表,列表里面的元素是sql类型
三、HTTP请求
GET提交的数据会放在URL中,以?分割URL的传输数据
POST方法是把提交的数据放在HTTP包的请求体中
从flask中导入request对象
from flask import request
请求相关信息
request.method 提交的方法 request.args get请求提及的数据 request.form post请求提交的数据 request.values post和get提交的数据总和 request.cookies 客户端所带的cookie request.headers 请求头 request.path 不带域名,请求路径 request.full_path 不带域名,带参数的请求路径 request.script_root request.url 带域名带参数的请求路径 request.base_url 带域名请求路径 request.url_root 域名 request.host_url 域名 request.host 127.0.0.1:500 request.files
Flask关于request一些方法
一、post 请求 (Content-Type: application/json) 1.data = request.get_data() #一般使用这个 可以获取未经处理过的原始数据而不管内容类型,如果数据格式是json的,则取得的是json字符串,排序和请求参数一致 2.data = request.get_json() 将请求参数做了处理,得到的是字典格式的,因此排序会打乱依据字典排序规则 3.data = request.data 可以获取未经处理过的原始数据,如果数据格式是json的,则取得的是json字符串,排序和请求参数一致 4.data = request.json 二、get请求 1.request.args.get("key")可以获取单个的值 2.request.args可以获取get请求的所有参数返回值是ImmutableMultiDict类型 3.requestValues.to_dict()将获得的参数转换为字典
1.GET请求使用request获取url中数据
访问:http://127.0.0.1:5000/name?page=1
使用request的属性获取url request.path /name request.full_path /name?page=1 request.values['page'] 1 #获取参数page的值 request.args.get('page') 1 #和上面一样也是获取参数page的值
代码示例
@app.route('/name',methods=['POST','GET']) def hello_world(): print(request.values['page']) #1 #获取路由传递参数 print(request.args.get('page')) #1 return 'Hello World!'
2.POST请求 post请求:会给服务器提交一些数据
先了解一下render_template:会去flask根目录下的template里面寻找文件,所以给的路径是相对路径
代码示例:将数据search_result和title传递到blog/index.html中
return render_template("blog/index.html", search=search_result, title=title)
request.form是专门用来针对接收表单数据的
request.form.get('username') #form表单设置的name值username request.form.get('password') #form表单设置的name值password
代码示例
# 获取get的请求参数 if request.method == 'GET': name = request.args.get('name') # 从get参数里获取名为name的参数 password = request.args.get('password') # 从get参数里获取名为name的参数 return '这是GET方法,请求获取的参数' # 获取post的请求参数(表单) if request.method == 'POST': # post方法多是需要修改数据库,并且都是表单提交上来的所以用form name = request.form.get('name') # 从get参数里获取名为name的参数 password = request.form.get('password') # 从get参数里获取名为name的参数 # 这里也可以操作把表单提交上来的数据存到数据库里,然后返回json数据 return '这是POST方法,请求的'
四、详解url
1. 动态路由传参
@app.route('/student_list/<student_id>/') #注意写<> def student_list(student_id): #这个和前面request获取路径上参数用法是不一样的 return '学生{}号的信息'.format(student_id)
动态路由的过滤
@app.route('/student_list/<int:student_id>/') #限定student_id必须是整数类型 def student_list(student_id): return '学生{}号的信息'.format(student_id)
默认转换器
DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, #默认的数据类型(字符串) 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, #数字类型 'float': FloatConverter, 'uuid': UUIDConverter, }
2.查询字符串传参(就是路由传参)
www.baidu.com/s?wd=python&ad=flask 这个?后的key=value便是查询字符串传参
通过request.args属性根据字符串中的key取出字符串的value
例如:https://127.0.0.1:5000/studet_name?name=xxx&age=xx
from flask import Flask,request @app.route('/student_name/') def school_name_list(): name=request.args.get('name') #获取路径中key=name的值,使用request.values['name']也可以 age=request.args.get('age') #获取路径中key=age的值 return "学生的姓名为{},年龄为{}".format(name,age)
3.url_for()的使用
url_for()的原理:利用视图函数名字一般不会改变的特性,利用视图函数的名字去动态精准的获取url
url_for('视图函数名字') #输出该视图函数url
例子:
from flask import Flask,url_for app = Flask(__name__) app.config.update(DEBUG=True) @app.route('/') def demo1(): print(url_for("book")) #/book_list/ # 注意这个引用的是视图函数的名字 字符串格式,输出是url地址 print(type(url_for("book"))) # <class 'str'> return url_for("book") #/book_list/ @app.route('/book_list/') def book(): return 'flask_book' if __name__ == "__main__": app.run()
url_for如何处理动态路由的视图函数
如果想获取动态路由,必须以关键字实参的形式为动态的path部分赋值,注意动态的path部分必须被赋值
@app.route('/demo2/') def demo2(): student_url = url_for('student', id=5, name='mark',age=18) #id是动态path的key必须赋值,name和age作为查询字符串传入 # name 将作为查询字符串传入 print(student_url) #/student/5/?name=mark&age=18 return student_url @app.route('/student/<int:id>/') def student(id): return 'student {}'.format(id)
url_for如何为url添加查询字符串
在路径后面拼出来查询字符串,以关键字实参的形式放到url_for()里面作为参数,会自动拼成路径
@app.route('/demo3/') def demo3(): school_url = url_for('school', school_level='high', name='college') # 具体要拼接的查询参数 以关键字实参的形式写在url_for里 print(school_url) #/school/?school_level=high&name=college return school_url @app.route('/school/') def school(): return 'school message'
注意:url_for()不仅可以在视图函数中使用也可以在前端使用
前端使用方法: href={{ url_for('blog.analysis',id =post['id'])}} #和在视图函数中一样使用url_for('视图函数名'),也可以设置参数