day4
CSRF
CSRF 知道攻击原理(重点)
在 FlaskForm 中实现校验
- 设置应用程序的 secret_key
- 用于加密生成的 csrf_token 的值
app.secret_key = "#此处可以写随机字符串#"
- 在模板的表单中添加以下代码
<form method="post">
{{ form.csrf_token() }}
{{ form.username.label }} {{ form.username }}<br/>
{{ form.password.label }} {{ form.password }}<br/>
{{ form.password2.label }} {{ form.password2 }}<br/>
{{ form.submit }}
</form>
- 渲染出来的前端页面为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3fPCAKRa-1573114395531)(…/assets/flaskwtf_csrftoken.png)]
设置完毕,cookie 中的 csrf_token 不需要我们关心,会自动帮我们设置
单独使用
- 设置应用程序的 secret_key
- 用于加密生成的 csrf_token 的值
app.secret_key = "#此处可以写随机字符串#"
- 导入 flask_wtf.csrf 中的 CSRFProtect 类,进行初始化,并在初始化的时候关联 app
from flask.ext.wtf import CSRFProtect
CSRFProtect(app)
- 如果模板中有表单,不需要做任何事。与之前一样:
<form method="post">
{{ form.csrf_token }}
...
</form>
- 但如果模板中没有表单,你仍需要 CSRF 令牌:
<form method="post" action="/">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>
数据库
ORM
优点 :
只需要面向对象编程,不需要面向数据库编写代码
对数据库的操作都转化成对类属性和方法的操作
实现了数据模型与数据库的解耦,屏蔽了不同数据库操作上的差异
缺点
- 相比较直接使用SQL语句操作数据库,有性能损失.
- 根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.
安装
sudo apt-get build-dep python-mysqldb
安装flask-sqlalchemy
pip install flask-sqlalchemy
安装mysqldb
pip install flask-mysqldb
数据库的连接设置
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#设置连接数据库的URL
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
# 动态追踪修改设置,如未设置只会提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
#查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
# 定义模型
class Author(db.Model):
__tablename__='authors'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique=True)
# 关联
books = db.relationship('Book',backref='author')
class Book(db.Model):
__tablename__='books'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique=True)
# 外键
author_id = db.Column(db.Integer,db.ForeignKey(Author.id))
"""
查询所有用户数据
User.query.all()
查询有多少个用户
User.query.count()
查询第1个用户
User.query.first()
查询id为4的用户[3种方式]
User.query.get(4)
User.query.filter_by(id = 4).first()
User.query.filter(User.id == 4).first()
查询名字结尾字符为g的所有数据[开始/包含]
User.query.filter(User.name.endwith('g')).all()
查询名字不等于wang的所有数据[2种方式]
User.query.filter(User.name != 'wang').all()
User.query.filter(not_(User.name == 'wang')).all()
查询名字和邮箱都以 li 开头的所有数据[2种方式]
User.query.filter(User.name.startswith('li'),User.email.startswith('li')).all()
User.query.filter(and_(User.name.startswith('li'),User.email.startswith('li')))
查询password是 `123456` 或者 `email` 以 `itheima.com` 结尾的所有数据
User.query.filter(or_(User.password == '123456',User.email.endswith('itheima.com'))).all()
查询id为 [1, 3, 5, 7, 9] 的用户列表
User.query.filter(User.id.in_([1,3,5,7,9])).all()
查询name为liu的角色数据
User.query.filter(User.name == 'liu').first().role
查询所有用户数据,并以邮箱排序
User.query.order_by(User.email).all()
User.query.order_by(User.email.asc()).all()
User.query.order_by(User.email.desc()).all()
每页3个,查询第2页的数据
paginate = User.query.paginate(2,3) # 第一个参数代表第几页,第二个参数代表每页几个
paginate.items 当前页数据
paginate.pages 总页数
paginate.page 当前页
"""
常用的SQLAlchemy查询过滤器
过滤器 | 说明 |
---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 |
limit | 使用指定的值限定原查询返回的结果 |
offset() | 偏移原查询返回的结果,返回一个新查询 |
order_by() | 根据指定条件对原查询结果进行排序,返回一个新查询 |
group_by() | 根据指定条件对原查询结果进行分组,返回一个新查询 |
常用的SQLAlchemy查询执行器
方法 | 说明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,如果未查到,返回None |
first_or_404() | 返回查询的第一个结果,如果未查到,返回404 |
get() | 返回指定主键对应的行,如不存在,返回None |
get_or_404() | 返回指定主键对应的行,如不存在,返回404 |
count() | 返回查询结果的数量 |
paginate() | 返回一个Paginate对象,它包含指定范围内的结果 |
查询数据后删除
user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()
更新数据
user = User.query.first()
user.name = 'dong'
db.session.commit()
User.query.first()