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.csdn.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('视图函数名'),也可以设置参数
原文地址:https://www.cnblogs.com/wangcuican/p/13089953.html