开源项目,可写在简历里
1 # 开源项目 sql审核平台 2 -https://gitee.com/cookieYe/Yearning 3 -https://gitee.com/rtttte/Archery
cbv加装饰器
1 from flask import Flask 2 from flask.views import MethodView 3 4 app = Flask(__name__) 5 6 app.debug = True 7 8 9 # 登录认证--->不能公用--》要么只能给fbv用,要么只能给cbv用 10 def auth(func): 11 def inner(*args, **kwargs): 12 print(args) # cbv,会有第一个参数 self:(<__main__.UserView object at 0x000001B1ECF5E5E0>,) ,如果是fbv,就是空的:访问根路径 13 res = func(*args, **kwargs) 14 print('装饰器走了') 15 return res 16 17 return inner 18 19 20 @app.route('/', endpoint='index') 21 @auth 22 def index(): 23 return 'hello flask' 24 25 26 # class UserView(MethodView): 27 # @auth 28 # def get(self): 29 # return 'user-get' 30 31 # 上述直接加不够用,所以我们选择下述方式 32 # 装饰器加在类上,类中加方法 33 34 class UserView(MethodView): 35 decorators = [auth] # 顺序从下往上 36 37 # methods = ['POST'] 访问不到get 38 def get(self): 39 return 'user-get' 40 41 42 app.add_url_rule('/user', endpoint='user', view_func=UserView.as_view('user')) 43 if __name__ == '__main__': 44 app.run()
。
。
闪现(flash)
# 1 flask中得闪现存放数据的地方,一旦取了,数据就没了
-实现跨请求间传递数据
# 2 django中有没有类似的东西?
-message 消息框架
# 3 基本使用
1 设置:flash('欢迎你:lqz')
2 取:get_flashed_messages()
# 4 根据标签设置和取值
flash('超时错误',category="x1")
get_flashed_messages(category_filter=['x1'])
1 案例 2 3 from flask import Flask, request, render_template, redirect, flash, get_flashed_messages 4 5 app = Flask(__name__) 6 app.debug = True 7 # 要用闪现,必须指定secret_key--》闪现内部使用session实现的 8 app.secret_key = 'asdfasdf' 9 10 11 @app.route('/login', methods=['GET', 'POST']) 12 def login(): 13 if request.method == 'GET': 14 return render_template('login.html') 15 else: 16 username = request.form.get('username') 17 password = request.form.get('password') 18 if username == 'jh' and password == '123': 19 # 使用闪现,放个数据 20 flash('欢迎你:66') 21 flash('ss') 22 flash('ee') 23 return redirect('/') 24 else: 25 flash('用户名密码错误') 26 return redirect('/') 27 28 29 @app.route('/') 30 def index(): 31 # 获取闪现的数据 32 print(get_flashed_messages()) 33 return render_template('index.html') 34 35 36 if __name__ == '__main__': 37 app.run() 38 39 40 -------------------------------------------------------------------------- 41 前端登录页面 42 43 <!DOCTYPE html> 44 <html lang="en"> 45 <head> 46 <meta charset="UTF-8"> 47 <title>Login</title> 48 </head> 49 <body> 50 <form action="{{ url_for('login') }}" method="post"> 51 <p>用户名:<input type="text" name="username"></p> 52 <p>密码:<input type="password" name="password"></p> 53 <input type="submit" value="提交"> 54 </form> 55 </body> 56 </html> 57 58 59 --------------------------------------------------------------------------- 60 前端首页 61 62 <!DOCTYPE html> 63 <html lang="en"> 64 <head> 65 <meta charset="UTF-8"> 66 <title>Title</title> 67 68 </head> 69 <body> 70 <h1>首页</h1> 71 <h2>{{get_flashed_messages()[0]}}</h2> 72 </body> 73 74 </html>
django中使用
################ 1 基础配置############ INSTALLED_APPS = [ ... 'django.contrib.messages', ... ] # 在django setting.py 取消注释的message app MIDDLEWARE = [ ... 'django.contrib.messages.middleware.MessageMiddleware', ... ] # 在django setting.py 取消注释的message 的中间件 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ ... 'django.contrib.messages.context_processors.messages', ], } } ] ################ 2 设置存放位置############ MESSAGE_STORAGE = "django.contrib.messages.storage.session.SessionStorage" ################ 3 放入值############ #添加message from django.contrib import messages def concel_order(request): messages.add_message(request, messages.SUCCESS, "删除成功1") messages.add_message(request, messages.SUCCESS, "删除成功2") return redirect("/order/control/") ################ 4 视图函数中取############ # 在视图函数中添加messages模块 # 再通过messages.add_message导入提示信息 # 在视图函数中import get_messages模块获取添加的提示信息 def control_order(request): if request.method == "GET": from django.contrib.messages.api import get_messages m1 = get_messages(request) print(m1) ################ 5 模板中取############ # 在html模板中添加for循环拿到message <div> {% for obj in messages %} <ul>{{ obj.message }}</ul> {% endfor %} </div>
。
。
g对象
# 1 g 对象,是一个全局对象--》global的缩写,global是关键字,不能用来做变量,所以它叫了g
# 2 g在当次请求中,可以放入值,可以取出值
-我们使用:index 视图函数---》内部又调用了add--》add()又调用了aa()-->如果有参数,需要依次传入
-通过g对象,我们可以把参数放到g中,以后直接从g中取即可
# 3 g和request对象都在当次请求中有效
-我们一般不直接把数据放到request对象中
-因为可能会污染数据
# 4 django中没有g
1 案例 2 3 from flask import Flask, g, request 4 5 app = Flask(__name__) 6 7 app.debug = True 8 app.secret_key = 'asdfasdf' 9 10 11 @app.before_request 12 def before(): 13 if 'index' in request.full_path: 14 g.name = 'index' 15 request.name = 'index' 16 else: 17 g.name = '其他' 18 request.name = '其他' 19 20 21 def add(): 22 print(g.name) 23 print(request.name) 24 25 26 @app.route('/index') 27 def index(): 28 print(g.name) 29 add() 30 return 'hello' 31 32 33 @app.route('/home') 34 def home(): 35 print(g.name) 36 return 'home' 37 38 39 if __name__ == '__main__': 40 app.run()
g和session区别
# g 只在当前请求中有效 # session可以跨 请求 # 闪现可以跨请求--》本质就是session--》用一次就没了
。
。
蓝图(blueprint)
# 1 使用蓝图划分目录 蓝图使用步骤 1 蓝图类实例化得到一个对象 from flask import Blueprint # 第一个参数是蓝图名 order_blue=Blueprint('order',__name__) 2 在视图函数上,使用蓝图注册路由-->蓝图也有请求扩展 @order_blue.before_request def before(): print('来了') @order_blue.route('/order') def order(): return 'order-order-order' 3 在app中注册蓝图 app.register_blueprint(user_blue)
蓝图的使用
1 # blueprint 翻译过来的,称之为蓝图 2 3 # 蓝图干嘛的? 4 作用:之前我们写的url和视图函数都是处在同一个文件,如果项目比较大的话, 5 这显然不是一个合理的结构,而蓝图可以优雅的帮我们实现这种需求。 6 蓝图的作用就是 划分目录 让我们的Flask项目,结构更加清晰 7 8 实现项目达到分层解耦合的作用 9 蓝图 (Blueprint) 是 Flask 程序的模块化处理机制 10 它是一个存储视图方法的集合, 一个项目可以具有多个蓝图对象 11 蓝图可以单独拥有自己的模板、静态文件的目录 12 13 ---------------------------------------------- 14 ---------------------------------------------- 15 16 # 不用蓝图,划分目录,适合非常小型的项目 17 18 no_blueprint_flask # 项目名 19 src # 核心代码位置 20 __init__.py # 包 里面实例化得到了app对象, 21 models.py # 放表模型 22 views.py # 放视图函数 23 24 static # 放静态资源 25 templates # 放模板 26 home.html # 模板 27 28 manage.py # 启动文件 29 settings.py 30 31 --------------------------------------------------- 32 33 # __init__.py 文件 34 from flask import Flask 35 36 app = Flask(__name__, template_folder='../templates', static_folder='../static') 37 # app.config['DEBUG'] = True 38 # app.secret_key = 'jckopjoeko8415561' 39 app.config.from_pyfile('settings.py') 40 from . import views 41 42 # 这句话不写,manage.py文件里面app.run() 没有用 43 # 因为views.py文件整体都没有加载,所以添加路由的代码也就没有走了, 44 # 所以虽然项目启动起来,但是路由匹配不上!!! 45 46 --------------------------------------------------- 47 # views.py 文件 48 49 from . import app 50 from flask import render_template 51 52 # .在路径中表示当前目录 53 # ..在路径中表示上一层目录 54 # ..\..在路径中表示上上一层目录 55 # 视图函数 56 57 @app.route('/index') 58 def index(): 59 return 'index' 60 61 62 @app.route('/home', defaults={'name': 'lqz'}) 63 def home(name): 64 name = name 65 return render_template('home.html', name=name) 66 67 --------------------------------------------------- 68 69 # manage.py 70 from src import app 71 72 if __name__ == '__main__': 73 app.run()
使用蓝图,划分小型项目目录
1 little_blueprint # 项目名 2 3 src # src目录下放项目关键的文件 4 __init__.py # 包 5 models.py # 表模型 6 7 static # 静态文件目录 8 1.jpg # 图片 9 templates # 模板文件目录 10 user.html # 模板 11 12 views # 视图函数目录 13 order.py # 订单相关视图 14 user.py # 用户相关视图 15 16 manage.py # 启动文件 17 settings.py 18 19 ---------------------------------------------- 20 21 # __init__.py 文件 22 from flask import Flask 23 import sys 24 from pathlib import Path 25 26 BASE_DIR = Path(__file__).resolve().parent # D:\pythonProject\2023flask1\src 27 sys.path.append(str(BASE_DIR)) 28 29 app = Flask(__name__, template_folder='templates', static_folder='static') 30 # app.config['DEBUG'] = True 31 # app.secret_key = 'jckopjoeko8415561' 32 from settings import DevelopmentConfig 33 app.config.from_object(DevelopmentConfig) 34 35 36 37 from .views.user import user_bp 38 from .views.order import order_bp 39 app.register_blueprint(user_bp) # 注册蓝图对象!!! 40 app.register_blueprint(order_bp) # 注册蓝图对象!!! 41 42 ---------------------------------------------- 43 44 # user.py 文件 蓝图类实例化生成对象 45 from flask import Blueprint, render_template 46 47 user_bp = Blueprint('user', __name__) 48 # 第一个参数表示蓝图的名称随便起 第二个参数 __name__ 表示蓝图所在的模块 49 50 @user_bp.route('/user/home', defaults={'name': 'teng'}) 51 def home(name): 52 return render_template('home.html', name=name) 53 54 ---------------------------------------------- 55 ---------------------------------------------- 56 57 # order.py 文件 58 from flask import Blueprint 59 60 order_bp = Blueprint('order', __name__) 61 62 63 # 蓝图对象也有自己的请求扩展,但只对当前文件下的视图函数起作用,跨文件就没用了!!! 64 # 如果想该请求扩展,对所有视图函数都有用, 就用 @app.before_request来装饰下面的函数了 65 # 如果是写对所有视图函数都有用的请求扩展的话,代码可以写到init文件里面去了 66 67 @order_bp.before_request # 该请求扩展函数,只会对被该蓝图对象管理的视图函数起作用!!! 68 def before(): 69 print('我来了') 70 71 72 @order_bp.route('/order/home') 73 def home(): 74 return 'order的home页面' 75 76 77 @order_bp.route('/order/list1') 78 def list1(): 79 return 'order的list页面' 80 81 # 该蓝图对象的请求扩展,不会对其他文件里面的视图函数起作用!!! 82 ---------------------------------------------- 83 84 # manage.py 85 from src import app 86 87 if __name__ == '__main__': 88 app.run()
使用蓝图,划分大型项目目录 多个app,像django一样
1 big_blueprint # 项目名 2 src # 核心文件 3 __init__.py # 包 4 5 6 admin # admin的app 7 static # 静态文件目录 8 templates # 模板文件目录 9 __init__.py # 包 10 models.py # 表模型 11 views.py # 视图函数 12 13 home # home的app 和admin的app一样,可以有单独的静态文件、模板等 14 order # order的app 15 16 manage.py # 启动文件 17 settings.py # 配置文件 18 19 20 ------------------------------------------------------ 21 22 # manage.py 启动文件 23 24 from src import app 25 26 if __name__ == '__main__': 27 app.run() 28 29 ------------------------------------------------------ 30 31 # src包 下的__init__文件 32 # 主要就是生成app对象 添加配置 导入蓝图对象 注册蓝图对象 蓝图对象加路由前缀等功能 33 34 from flask import Flask 35 36 app = Flask(__name__) 37 38 from settings import DevelopmentConfig 39 app.config.from_object(DevelopmentConfig) 40 41 from src.admin import admin_bp 42 from src.order import order_bp 43 from src.home import home_bp 44 45 46 # 注册蓝图 47 # 注意在注册蓝图前,要检查下被蓝图对象管理的视图函数所在的文件,有没有被导入 48 # 一般就在创建蓝图对象的代码下面,执行导入视图函数所在的文件,才能完成路由的注册!!! 49 app.register_blueprint(admin_bp, url_prefix='/admin') 50 app.register_blueprint(order_bp, url_prefix='/order') 51 app.register_blueprint(home_bp, url_prefix='/home') 52 53 54 # url_prefix 路由前缀,和django的总路由有点相似, 55 # 蓝图下面的路由,会自动拼接的路由前缀的后面 56 57 ------------------------------------------------------ 58 ------------------------------------------------------ 59 60 # admin的app下的__init__ 61 62 from flask import Blueprint 63 64 # 蓝图使用自己的静态文件与自己的模板 65 admin_bp = Blueprint('admin', __name__, static_folder='static', template_folder='templates') 66 67 # 导入被该蓝图对象管理的views.py文件,这样才能完成路由的注册 68 from src.admin import views 69 70 71 ------------------------------------------------------ 72 # admin的app下的views.py 73 74 from flask import render_template, request, session, redirect 75 from . import admin_bp 76 from src.wrappers import auth 77 78 79 @admin_bp.before_request 80 def before1(): 81 print('admin请求来了会执行') 82 83 84 @admin_bp.after_request 85 def after1(response): 86 print('admin请求走了会执行') 87 return response 88 89 90 @admin_bp.route('/home', defaults={'name': 'teng'}) 91 def home(name): 92 return render_template('admin_home.html', name=name) 93 94 95 @admin_bp.route('/login', methods=['GET', 'POST']) 96 def login(): 97 if request.method == 'GET': 98 return render_template('login.html') 99 else: 100 name = request.form.get('username') 101 password = request.form.get('password') 102 session['name'] = name 103 print(session) # <SecureCookieSession {'name': 'teng'}> 104 return redirect('/admin/home') 105 106 107 # 搞了一个登录的装饰器 108 @admin_bp.route('/index') 109 @auth 110 def index(): 111 return '哈哈哈' 112 113 ------------------------------------------------------ 114 115 # src目录下面的wrappers.py 文件里面的登录装饰器函数 116 117 from flask import session,redirect 118 119 def auth(func): 120 def inner(*args, **kwargs): 121 # print(session.get('name')) 122 if session.get('name'): 123 res = func(*args, **kwargs) 124 return res 125 else: 126 return redirect('/admin/login') 127 return inner 128 129 ------------------------------------------------------ 130 131 # settings.py 配置文件 132 133 class BASE(object): 134 DEBUG = False 135 136 137 class ProductionConfig(BASE): 138 SECRET_KEY = 'jckopjoeko8415561' 139 HAHA = 'heihei' 140 141 142 class DevelopmentConfig(BASE): 143 SECRET_KEY = 'jckopjoeko8415561' 144 HAHA = 'heihei' 145 DEBUG = True
flask-session
# 1 第三方 flask-session,可以把session的内容保存在服务端
-redis
-数据库
-文件。。。
# 2 安装并使用
pip3 install flask-session
1 # 方式一: 2 # from flask_session.redis import RedisSessionInterface 3 # import redis 4 # from flask import Flask,session 5 # 6 # app = Flask(__name__) 7 # app.secret_key = 'adsfasdfads' 8 # conn = redis.Redis(host='127.0.0.1', port=6379) 9 # # 1 client:redis链接对象 10 # # 2 key_prefix:放到redis中得前缀 11 # # 3 use_signer:是否使用secret_key 加密 12 # # 4 permanent:关闭浏览器,cookie是否失效 13 # # 5 生成session_key的长度 14 # app.session_interface = RedisSessionInterface(app, client=conn, key_prefix='session', use_signer=True, permanent=True, 15 # sid_length=32) 16 # app.debug = True 17 18 # 方式二: 19 from flask import Flask, session 20 from flask_session import Session 21 from redis import Redis 22 23 app = Flask(__name__) 24 app.config.from_pyfile('./settings.py') 25 Session(app) # 核心跟第一种方式一模一样 26 27 28 @app.route('/index') 29 def index(): 30 session['name'] = 'jh' 31 return 'index' 32 33 34 if __name__ == '__main__': 35 app.run() 36 37 ------------------------------------ 38 方式二中settings里的配置 39 40 from redis import Redis 41 42 SESSION_TYPE = 'redis' 43 SESSION_REDIS = Redis(host='127.0.0.1', port='6379') 44 SESSION_KEY_PREFIX = 'jh'
源码
1 # 1 open_session 2 def open_session(self, app, request): 3 # 1 取到前端传入,在cookie中得随机字符串 4 sid = request.cookies.get(app.config["SESSION_COOKIE_NAME"]) 5 if not sid: 6 sid = self._generate_sid(self.sid_length) 7 # 不为空--》把sid传入--》得到了session对象 8 return self.session_class(sid=sid, permanent=self.permanent) 9 if self.use_signer: 10 try: 11 sid = self._unsign(app, sid) 12 except BadSignature: 13 sid = self._generate_sid(self.sid_length) 14 return self.session_class(sid=sid, permanent=self.permanent) 15 return self.fetch_session(sid) 16 17 def fetch_session(self, sid): 18 # 随机字符串 19 prefixed_session_id = self.key_prefix + sid 20 # 从redis中,取出 key 为 前缀+随机字符串 对应的value的值 21 value = self.redis.get(prefixed_session_id) 22 if value is not None: 23 try: 24 # 解密成字符串 25 session_data = self.serializer.loads(value) 26 # 把解密后的数据,组装到 session对象中 27 return self.session_class(session_data, sid=sid) 28 except pickle.UnpicklingError: 29 return self.session_class(sid=sid, permanent=self.permanent) 30 return self.session_class(sid=sid, permanent=self.permanent) 31 32 33 # 2 save_session 34 def save_session(self, app, session, response): 35 if not self.should_set_cookie(app, session): 36 return 37 domain = self.get_cookie_domain(app) 38 path = self.get_cookie_path(app) 39 if not session: 40 if session.modified: 41 self.redis.delete(self.key_prefix + session.sid) 42 response.delete_cookie( 43 app.config["SESSION_COOKIE_NAME"], domain=domain, path=path 44 ) 45 return 46 47 expiration_datetime = self.get_expiration_time(app, session) 48 serialized_session_data = self.serializer.dumps(dict(session)) 49 # 放到redis中 50 self.redis.set( 51 name=self.key_prefix + session.sid, 52 value=serialized_session_data, 53 ex=total_seconds(app.permanent_session_lifetime), 54 ) 55 # 把session 对应的 随机字符串放到 cookie中 56 self.set_cookie_to_response(app, session, response, expiration_datetime) 57 58 59 # 两个点 60 - session的前缀如果不传,默认:config.setdefault('SESSION_KEY_PREFIX', 'session:') 61 - session过期时间:通过配置,如果不写,会有默认 62 'PERMANENT_SESSION_LIFETIME': timedelta(days=31),#这个配置文件控制 63 -设置cookie时,如何设定关闭浏览器则cookie失效 64 permanent=False 65 app.config['SESSION_PERMANENT'] = False
。
。
wtforms
# django--->forms组件
-1 校验数据
-2 错误处理
-3 渲染页面
# flask--》第三方的wtforms
pip3 install wtforms
1 from flask import Flask, render_template, request, redirect 2 from wtforms import Form 3 from wtforms.fields import simple 4 from wtforms import validators 5 from wtforms import widgets 6 7 app = Flask(__name__, template_folder='templates') 8 app.debug = True 9 10 11 class LoginForm(Form): 12 name = simple.StringField( 13 label='用户名', 14 validators=[ 15 validators.DataRequired(message='用户名不能为空.'), 16 validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d') 17 ], 18 widget=widgets.TextInput(), 19 render_kw={'class': 'form-control'} 20 ) 21 pwd = simple.PasswordField( 22 label='密码', 23 validators=[ 24 validators.DataRequired(message='密码不能为空.'), 25 validators.Length(min=8, message='密码长度必须大于%(min)d'), 26 validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}", 27 message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符') 28 ], 29 widget=widgets.PasswordInput(), 30 render_kw={'class': 'form-control'} 31 ) 32 33 34 @app.route('/login', methods=['GET', 'POST']) 35 def login(): 36 if request.method == 'GET': 37 form = LoginForm() 38 return render_template('login.html', form=form) 39 else: 40 form = LoginForm(formdata=request.form) 41 if form.validate(): 42 print('用户提交数据通过格式验证,提交的值为:', form.data) 43 else: 44 print(form.errors) 45 return render_template('login.html', form=form) 46 47 48 if __name__ == '__main__': 49 app.run() 50 51 52 --------------------------------------------------------------------------- 53 前端页面 54 55 <!DOCTYPE html> 56 <html lang="en"> 57 <head> 58 <meta charset="UTF-8"> 59 <title>登录页面</title> 60 </head> 61 <body> 62 <h1>登录</h1> 63 <form method="post"> 64 {{ form.hidden_tag() }} <!-- 用于防止CSRF攻击 --> 65 <p>{{ form.name.label }} {{ form.name() }} {% if form.name.errors %}{{ form.name.errors[0] }}{% endif %}</p> 66 <p>{{ form.pwd.label }} {{ form.pwd() }} {% if form.pwd.errors %}{{ form.pwd.errors[0] }}{% endif %}</p> 67 <input type="submit" value="提交"> 68 </form> 69 </body> 70 </html> 71 72 73 =============================== 74
标签:__,return,name,flask,app,flash,session,import From: https://www.cnblogs.com/liuliu1/p/18249614