心得:加油 ,你选择的是正确的路
一、Flask路由
endpoint - 默认是视图函数名url_for 反向地址
methods 指定视图函数的请求方式,默认GET,是一个可迭代的列表或元组
defaults={“nid”:1} 指定视图函数的默认参数
strict_slashes=False 是否严格遵循路由规则/login/
不可以访问
redirect_to="/login" 永久跳转地址 301
动态路由参数:
/<int:nid> /<string:str> /<nid>
视图函数中需要有参数接收动态路由参数
from flask import Flask,render_template,redirect,url_for
app=Flask(__name__)
@app.route("/")
def index():
return "123"
@app.route("/login/<id>",methods=["GET","POST"],endpoint="login",defaults={"nid":1})
def login(id,nid):
print(nid)
print(id)
return redirect(url_for('index'))
app.run()
二、Flask中的实例化配置
template_folder = “temp” # template模板目录, 默认当前项目中的 templates 目录
static_folder = “jingtaiwenjianmulu” 目录
static_url_path = “/static” 访问路径
static_host =
host_matching = False, # 如果不是特别需要的话,慎用,否则所有的route 都需要host=""的参数
subdomain_matching = False, # 理论上来说是用来限制SERVER_NAME子域名的,但是目前还没有感觉出来区别在哪里
instance_path = None, # 指向另一个Flask实例的路径
instance_relative_config = False # 是否加载另一个实例的配置
root_path = None # 主模块所在的目录的绝对路径,默认项目目录
from flask import Flask
app = Flask(__name__,template_folder="templates",static_folder="haha",static_url_path="/statics")
app.secret_key="hahaha"
#static_folder 加载本地精通文件地址
#static_url_path 将本地得静态文件全部发送到网页端,类似于send_file,然后html端调用
三、蓝图 Blueprint
创建蓝图,在主界面可以注册使用,它的作用就是将 功能 与 主服务 分开
users.py
from flask import Blueprint,render_template
users_blue = Blueprint("users",__name__,template_folder="user_temp",url_prefix="/user")
#url_prefix在路由前拼接路径,前缀
@users_blue.route("/user_add") #/user/user_add
def user_add():
return render_template("user_add.html")
app.py
from flask import Flask,request,session,render_template,redirect,url_for,send_file
import users
app = Flask(__name__,template_folder="temp",static_folder="jingtaiwenjianmulu",static_url_path="/static")
app.register_blueprint(users.users_blue) #注册就可以使用
四、特殊装饰器
#请求进入视图函数之前
@app.before_request
def is_login():
print("be1")
if request.path == "/login":
return None
if session.get("user"):
return None
else:
return redirect("/login")
#结束视图函数之后,返回客户端之前
@app.after_request
def af3(res):
print("af3")
return res
五、Flask的CBV
CBV的简单写法,在app中注册add_url_rule()
from flask import Flask,request,render_template,redirect,url_for
from flask import views #CBV继承MethodView
class LoginClass(views.MethodView):
def get(self):
print(url_for("login"))
return render_template("login.html")
def post(self):
return "123"
# self.add_url_rule(rule, endpoint, f, **options)
app.add_url_rule("/login",view_func=LoginClass.as_view("login"))
if __name__ == '__main__':
app.run(debug=True)
六、Flask的session
flask自带session
flask_session 第三方包session
from flask import Flask,request,session
from redis import Redis #实例化Redis
from flask_session import Session
app = Flask(__name__) # type:Flask
#配置数据库信息
app.config["SESSION_TYPE"] = "redis"
app.config["SESSION_REDIS"] = Redis("127.0.0.1",6379,db=7)
#
Session(app) #用flask_session将flask的session替换掉
@app.route("/")
def index():
session["user"] = "JWB"
# 87fd0ba1-6c36-44be-bc36-2a95b764e122
return "123"
if __name__ == '__main__':
app.run(debug=True)
七、WTForms(Flask) - MoudelForm(Django)
一般情况下字段都在simple中,特殊的字段在core中。验证字段的结果在errors中
from flask import Flask,request,render_template
from flask import views
from wtforms.fields import simple,core
from wtforms import Form
from wtforms import validators
# from wtforms import widgets
class RegForm(Form):
username = simple.StringField(
label="用户名",
validators=[
validators.DataRequired(message="不能为空"),
validators.Length(min=3, max=5, message="不能小于3位,不能大于5位")
],
# widget=widgets.TextInput(),
render_kw={"class": "my_username"}
)
nickname = simple.StringField(
label="昵称",
validators=[
validators.DataRequired(message="不能为空"),
],
# widget=widgets.TextInput(),
render_kw={"class": "my_username"}
)
password = simple.PasswordField(
label="密码",
validators=[
validators.DataRequired(message="不能为空"),
validators.Length(min=6, max=6, message="密码必须为6位"),
validators.Regexp(regex="\d+", message="密码必须位数字"),
],
# widget=widgets.TextInput(),
render_kw={"class": "my_password"}
)
repassword = simple.PasswordField(
label="重复密码",
validators=[
validators.EqualTo(fieldname="password",message="两次密码不一致")
]
)
email = simple.StringField(
label="昵称",
validators=[
validators.Email(message="格式不正确"),
],
# widget=widgets.TextInput(),
render_kw={"class": "my_username"}
)
gender = core.RadioField(
label="性别",
coerce=int,
choices=(
(1,"女"),
(2,"男")
),
default=1
)
hobby = core.SelectMultipleField(
label="爱好",
coerce=int,
choices=(
(1, "小姐姐"),
(2, "小萝莉"),
(3, "小哥哥"),
(4, "小正太"),
(5, "阿姨"),
(6, "大叔"),
),
default=(1,2,5)
)
submit = simple.SubmitField(
label="提交"
)
app = Flask(__name__) # type:Flask
class RegClass(views.MethodView):
def get(self):
rf = RegForm()
return render_template("reg.html", rf=rf)
def post(self):
rf = RegForm(request.form)
if rf.validate():
return "123"
else:
return render_template("reg.html", rf=rf)
app.add_url_rule("/reg", view_func=RegClass.as_view("reg"))
if __name__ == '__main__':
app.run(debug=True)
<form action="" method="post">
{% for field in rf %}
<p>{{ field.label }}{{ field }}{{ field.errors.0 }}</p>
{% endfor %}
</form>
八、数据库连接池PooledDB应用
创建数据库连接池和使用数据库连接池:
from DBUtils.PooledDB import PooledDB
import pymysql
class MySQLhelper(object):
def __init__(self, host, port, dbuser, password, database):
self.pool = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
maxshared=3,
# 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
ping=0,
# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host=host,
port=int(port),
user=dbuser,
password=password,
database=database,
charset='utf8'
)
def create_conn_cursor(self):
conn = self.pool.connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
return conn,cursor
def fetch_all(self, sql, args):
conn,cursor = self.create_conn_cursor()
cursor.execute(sql,args)
result = cursor.fetchall()
cursor.close()
conn.close()
return result
def insert_one(self,sql,args):
conn,cursor = self.create_conn_cursor()
res = cursor.execute(sql,args)
conn.commit()
conn.close()
return res
def update(self,sql,args):
conn,cursor = self.create_conn_cursor()
res = cursor.execute(sql,args)
conn.commit()
print(res)
conn.close()
return res
sqlhelper = MySQLhelper("127.0.0.1", 3306, "root", "root", "crm")
res = sqlhelper.fetch_all("select * from rbac_role where id=%s",(2,))
print(res)
# res = sqlhelper.insert_one("insert into rbac_role VALUES (%s,%s)",(7,"jinwangba"))
# print(res)
# sqlhelper.update("update user SET name=%s WHERE id=%s",("yinwangba",1))