# 1 flask 介绍 web框架---》小而精--》第三方插件--》完成更丰富的功能--》自由选择第三方插件 # 2 wsgi协议:werkzeug:工具包 uwsgi,wsgiref djagno ,flask 要遵循wsgi协议 # 3 click 定制命令 -定制命令--》把excel中得数据---》导入到mysql的某个表中 # 4 python-dotenv:操作环境变量,设置和使用项目配置信息 # 5 flask快速使用 app=Flask(__name__) @app.route('/') def index(): return 'hello' # 6 运行 1 使用pycharm直接运行 2 flask命令运行:flask --app py文件名 run 3 右键运行:必须在py文件中写main 4 python命令运行:python xx.py 5 python 命令运行:python38 -m flask --app py文件名字 run 6 使用dotenv:flask app run # 7 虚拟环境 ###### Mac/linux # 创建虚拟环境 mkdir myproject cd myproject python3 -m venv .venv # 激活虚拟环境 . .venv/bin/activate ####Win # 创建虚拟环境 mkdir myproject cd myproject py -3 -m venv .venv # 激活虚拟环境 .venv\Scripts\activate # 8 debug模式 -错误信息会在浏览器显示 -改了代码会重启 # 9 fastapi介绍 # 10 登录跳转小案例
登录显示用户信息案例
py文件
from flask import Flask, request, render_template, redirect, session # 登录显示用户信息小案例 app = Flask(__name__) app.secret_key = 'asfasdf.asdf3932.asf3afasdfllg' app.debug = True # 常量--》写死用户信息 USERS = { 1: {'name': '刘亦菲', 'age': 18, 'gender': '男', 'text': "刘亦菲,1987年8月25日出生于湖北省武汉市,华语影视女演员、歌手,毕业于北京电影学院2002级表演系本科", 'img': 'https://img2.woyaogexing.com/2021/10/16/e3ccba623848430ba83209c0621a2256!400x400.jpeg'}, 2: {'name': '彭于晏', 'age': 28, 'gender': '男', 'text': "彭于晏,1982年3月24日出生于中国台湾省澎湖县,毕业于不列颠哥伦比亚大学,华语影视男演员。。。。。。。。", 'img': 'https://img2.woyaogexing.com/2021/10/16/e71aa35728c34313bccb4c371192990f!400x400.jpeg'}, 3: {'name': '迪丽热巴', 'age': 38, 'gender': '女', 'text': "迪丽热巴(Dilraba),1992年6月3日出生于中国新疆乌鲁木齐市,毕业于上海戏剧学院,中国内地影视女演员", 'img': 'https://img2.woyaogexing.com/2021/10/30/6a34146dde2d4f1c832463a5be1ed027!400x400.jpeg'}, 4: {'name': '亚瑟', 'age': 38, 'gender': '男', 'text': "亚瑟,是腾讯手游《王者荣耀》中一名战士型英雄角色,也是《王者荣耀》的新手英雄之一,既可攻又可守", 'img': 'https://img2.woyaogexing.com/2021/10/30/371b2aa7a03c4f53b7b1bc86f877d7d1!400x400.jpeg'}, } @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': # 返回模板 return render_template('login.html') else: # 取出用户名密码 username = request.form.get('username') password = request.form.get('password') if username == 'lqz' and password == '123': # 把登录信息写入到session中,一旦用session,必须指定 秘钥 session['name'] = username # 重定向 # return redirect('http://www.baidu.com') return redirect('/') else: # 返回模板,把错误信息渲染到模板 return render_template('login.html', error='用户名或密码错误') # 必须登录后,才能访问首页和详情页,如果没登录---》重定向到登录页面 @app.route('/') def index(): if session.get('name'): return render_template('index.html', users=USERS) else: return redirect('/login') @app.route('/detail/<int:id>') def detail(id): if session.get('name'): user = USERS.get(id) return render_template('detail.html', info=user) else: return redirect('/login') if __name__ == '__main__': app.run()
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> <title>登录</title> </head> <body> <div class="container col-xl-10 col-xxl-8 px-4 py-5"> <div class="row align-items-center g-lg-5 py-5"> <div class="col-lg-7 text-center text-lg-start"> <h1 class="display-4 fw-bold lh-1 mb-3">亚洲最大交友平台</h1> <p class="col-lg-10 fs-4">Bootstrap是Twitter推出的一个用于前端开发的开源工具包。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。目前,Bootstrap最新版本为5.0</p> </div> <div class="col-md-10 mx-auto col-lg-5"> <form class="p-4 p-md-5 border rounded-3 bg-light" method="post"> <div class="form-floating mb-3"> <input type="text" class="form-control" id="floatingInput" placeholder="[email protected]" name="username"> <label for="floatingInput">用户名</label> </div> <div class="form-floating mb-3"> <input type="password" class="form-control" id="floatingPassword" placeholder="Password" name="password"> <label for="floatingPassword">密码</label> </div> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me"> 记住密码 </label> </div> <button class="w-100 btn btn-lg btn-primary" type="submit">登录</button> <hr class="my-4"> <small class="text-muted">{{error}}</small> </form> </div> </div> </div> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> <title>Title</title> </head> <body> <div class="container"> <!-- 头部--> <div class="sticky-top"> <header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom"> <a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none"> <svg class="bi me-2" width="40" height="32"> <use xlink:href="#bootstrap"></use> </svg> <span class="fs-4">交友平台</span> </a> <ul class="nav nav-pills"> <li class="nav-item"><a href="#" class="nav-link active" aria-current="page">首页</a></li> <li class="nav-item"><a href="#" class="nav-link">女生</a></li> <li class="nav-item"><a href="#" class="nav-link">男生</a></li> <li class="nav-item"><a href="#" class="nav-link">国产</a></li> <li class="nav-item"><a href="#" class="nav-link">欧美</a></li> </ul> </header> </div> <!--轮播图--> <div> <div class="bd-example-snippet bd-code-snippet"> <div class="bd-example"> <div id="carouselExampleCaptions" class="carousel slide" data-bs-ride="carousel"> <div class="carousel-indicators"> <button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="0" class="" aria-label="Slide 1"></button> <button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="1" aria-label="Slide 2" class="active" aria-current="true"></button> <button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="2" aria-label="Slide 3" class=""></button> </div> <div class="carousel-inner"> <div class="carousel-item"> <img src="https://img.zcool.cn/community/[email protected]" alt="" width="100%" height="300"> <div class="carousel-caption d-none d-md-block"> <h5>激情绿荫</h5> <p>Some representative placeholder content for the first slide.</p> </div> </div> <div class="carousel-item active"> <img src="https://img2.baidu.com/it/u=2951612437,4135887500&fm=253&fmt=auto&app=138&f=JPEG" alt="" width="100%" height="300"> <div class="carousel-caption d-none d-md-block"> <h5>品牌雨伞</h5> <p>Some representative placeholder content for the second slide.</p> </div> </div> <div class="carousel-item"> <img src="https://img1.baidu.com/it/u=1417689082,3333220267&fm=253&fmt=auto&app=138&f=JPEG" alt="" width="100%" height="300"> <div class="carousel-caption d-none d-md-block"> <h5>家装节</h5> <p>Some representative placeholder content for the third slide.</p> </div> </div> </div> <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="visually-hidden">Previous</span> </button> <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="visually-hidden">Next</span> </button> </div> </div> </div> </div> <!-- 内容--> <div class="row row-cols-md-2" style="padding: 10px"> {% for k,v in users.items() %} <div class="card"> <div class="row " style="padding: 10px"> <img src="{{v.get('img')}}" alt="" class="col-md-4"> <div class="col-md-8"> <div class="card-body"> <h5 class="card-title">{{v['name']}}</h5> <p class="card-text">{{v.text}}</p> <p class="card-text"> <a href="/detail/{{k}}" class="btn btn-danger">查看详细</a> </p> </div> </div> </div> </div> {%endfor%} </div> <!-- table--> <div class="bd-example" style="margin-top: 30px"> <table class="table table-hover table-striped table-bordered"> <thead> <tr class="table-danger"> <th colspan="3" class="text-center">更多交友</th> </tr> </thead> <tbody> <tr class="table-success"> <th>杨幂</th> <td>女</td> <td>33</td> </tr> <tr class="table-warning"> <th scope="row">刘亦菲</th> <td>未知</td> <td>40</td> </tr> <tr class="table-success"> <th scope="row">彭于晏</th> <td>男</td> <td>23</td> </tr> <tr class="table-warning"> <th scope="row">陈奕迅</th> <td>男</td> <td>44</td> </tr> <tr class="table-success"> <th scope="row">薛之谦</th> <td>男</td> <td>36</td> </tr> <tr class="table-warning"> <th>李清照</th> <td>女</td> <td>未知</td> </tr> </tbody> </table> </div> <!--分页--> <div class="d-flex justify-content-center"> <ul class="pagination pagination-lg"> <li class="page-item"> <a class="page-link" href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> <li class="page-item"><a class="page-link" href="#">1</a></li> <li class="page-item"><a class="page-link" href="#">2</a></li> <li class="page-item"><a class="page-link" href="#">3</a></li> <li class="page-item"><a class="page-link" href="#">4</a></li> <li class="page-item"><a class="page-link" href="#">5</a></li> <li class="page-item"><a class="page-link" href="#">6</a></li> <li class="page-item"> <a class="page-link" href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </div> <!-- 尾部--> <div> <footer class="py-3 my-4"> <ul class="nav justify-content-center border-bottom pb-3 mb-3"> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">首页</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">特性</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">联系我们</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">资料获取</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">关于</a></li> </ul> <p class="text-center text-muted">Copyright © 1998 - 2029 liuqingzheng. All Rights Reserved. </p> </footer> </div> </div> </body> </html>
detail.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> <title>Title</title> </head> <body> <div class="container"> <div class="sticky-top"> <header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom"> <a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none"> <svg class="bi me-2" width="40" height="32"> <use xlink:href="#bootstrap"></use> </svg> <span class="fs-4">交友平台</span> </a> <ul class="nav nav-pills"> <li class="nav-item"><a href="#" class="nav-link active" aria-current="page">首页</a></li> <li class="nav-item"><a href="#" class="nav-link">女生</a></li> <li class="nav-item"><a href="#" class="nav-link">男生</a></li> <li class="nav-item"><a href="#" class="nav-link">国产</a></li> <li class="nav-item"><a href="#" class="nav-link">欧美</a></li> </ul> </header> </div> <div class="position-relative overflow-hidden p-3 p-md-5 m-md-3 text-center bg-light"> <div class="col-md-5 p-lg-5 mx-auto my-5"> <h1 class="display-4 fw-normal">{{info.name}}</h1> <img src="{{info.img}}" alt="" width="300px" height="300px" style="margin: 20px"> <p class="lead fw-normal">{{info.text}}</p> <a class="btn btn-outline-secondary" href="#">收藏</a> </div> <div class="product-device shadow-sm d-none d-md-block"></div> <div class="product-device product-device-2 shadow-sm d-none d-md-block"></div> </div> <div> <footer class="py-3 my-4"> <ul class="nav justify-content-center border-bottom pb-3 mb-3"> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">首页</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">特性</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">联系我们</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">资料获取</a></li> <li class="nav-item"><a href="#" class="nav-link px-2 text-muted">关于</a></li> </ul> <p class="text-center text-muted">Copyright © 1998 - 2029 liuqingzheng. All Rights Reserved. </p> </footer> </div> </div> </body> </html>
总结上述:
# 上面案例学到的 1 新手四件套 -返回字符串 return '字符串' -返回模板 return render_template('模板名字',参数=值,参数=值)--》参数可以在模板中使用 -返回重定向 return redirect('/index') -返回json格式 return jsonify(字典/列表) 2 session的使用 全局导入,直接使用,必须指定app.secret_key 设置值:session['key']=value 取值:session.get('key') 咱么写入到session后---》会以cookie形式放到浏览器中 之前django存到session中的数据--》存到django-session表中了 flask 放到session中的数据--》加密后,放到cookie中了 3 转换器 - int转换器 @app.route('/detail/<int:id>') def detail(id): -/detail/88--->把88给视图函数的第一个参数id 4 前端携带的数据,如何取 post请求的数据---》request.form-->字典 get地址中得数据---》request.args--》字典 5 模板语法---》跟dtl一样--》但是比dtl强大---》可以加括号执行
登录认证装饰器
# 写装饰器 def auth(func): def inner(*args, **kwargs): if session.get('name'): # 在执行真正被装饰的函数之前,就要认证完 res = func(*args, **kwargs) return res else: # 重定向到 登录页面 return redirect('/login') return inner # 使用 # 必须路由匹配完---》执行视图函数之前,做判断--》路由的装饰器是控制路由匹配的--》需要先执行,所以登录认证装饰器,放在下面 # 这样加了会报错---》每个路由,都会有个别名,如果不写,默认以函数名作为别名 # 如果视图函数加了装饰器---》函数名就变成了 inner?--》所有视图函数,都叫inner,导致 路由别名冲突了 # 1 装饰器加装饰器---wrapper装饰器--》改掉真正被装饰函数的名字 # 2 直接指定路由别名 @app.route('/',endpoint='index') @auth def index(): return render_template('index.html', users=USERS)
配置文件
# secret_key debug 后期如果使用数据库:数据库地址,用户名。。,自定义配置信息 # 1 方式一:放在app对象上,本质会放在 app.config 里面 # app.secret_key = 'asdfsdf' # app.debug = False # 2 方式二:放在app对象的config参数上 # app.config['DEBUG'] = True # app.config['HOST'] = '127.0.0.1' # 自己配置 # print(app.config) # 3 方式三:通过py文件设置 settings.py # app.config.from_pyfile('./settings.py') # 会加载settings中得大写的配置,都放到 config 中 # print(app.config) # 4 方式四:了解,使用环境变量----dot-env使用 # app.config.from_envvar("环境变量名称") # 5 方式五,常用,通过类 # app.config.from_object('settings.ProductionConfig') app.config.from_object('settings.DevelopmentConfig') print(app.config) # 6 其他 # app.config.from_json("json文件名称") # JSON文件名称,必须是json格式,因为内部会执行json.loads # app.config.from_mapping({'DEBUG': True})
----------------
# DEBUG = True # HOST = '127.0.0.222' class Config(object): DEBUG = False TESTING = False SECRET_KEY='123' DATABASE_URI = '127.0.0.1' class ProductionConfig(Config): DEBUG = False SECRET_KEY = 'asfasfd.ea33435asfasf' DATABASE_URI = '192.168.1.23' class DevelopmentConfig(Config): DEBUG = True DATABASE_URI = '127.0.0.1'
默认配置文件有哪些(了解)
{ 'DEBUG': get_debug_flag(default=False), 是否开启Debug模式 'TESTING': False, 是否开启测试模式 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, #秘钥 'PERMANENT_SESSION_LIFETIME': timedelta(days=31), #sessio过期时间 'USE_X_SENDFILE': False, 'LOGGER_NAME': None, 'LOGGER_HANDLER_POLICY': 'always', 'SERVER_NAME': None, 'APPLICATION_ROOT': None, 'SESSION_COOKIE_NAME': 'session', # 操作session--》成cookie到浏览器--》key值session 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12), 'TRAP_BAD_REQUEST_ERRORS': False, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': True, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, }
补充
# 后期项目中,可能使用配置中心 本地项目从配置中心获取配置信息--》写入到项目中 以后只需要改配置中心,所有项目配置都会变化 # 配置中心: -携程的阿波罗(Apollo) 携程阿波罗(Apollo):构建环境非常复杂–底层架构的颗粒度拆分的非常细 文档:https://www.apolloconfig.com/#/zh/README git地址:https://github.com/apolloconfig/apollo -Spring Cloud Config SpringCloud Config:属于spring体系,没有界面,配置文件内容存放在git上面 -Nacos(阿里)轻量级的配置中心 Nacos即可以作为注册中心,也可以作为分布式配置中心,轻量级的 git地址:https://github.com/alibaba/nacos/ 文档地址:https://nacos.io/zh-cn/docs/what-is-nacos.html
代码
from flask import Flask, jsonify app = Flask(__name__) # 1 方式一:放在app对象上,本质会放在 app.config 里面 # app.secret_key = 'asdfsdf' # app.debug = False # 2 方式二:放在app对象的config参数上 # app.config['DEBUG'] = True # app.config['HOST'] = '127.0.0.1' # 自己配置 # print(app.config) # 3 方式三:通过py文件设置 settings.py # app.config.from_pyfile('./settings.py') # 会加载settings中得大写的配置,都放到 config 中 # print(app.config) # 4 方式四:了解,使用环境变量----dot-env使用 # app.config.from_envvar("环境变量名称") # 5 方式五,常用,通过类 # app.config.from_object('settings.ProductionConfig') app.config.from_object('settings.DevelopmentConfig') print(app.config) # 6 其他 # app.config.from_json("json文件名称") # JSON文件名称,必须是json格式,因为内部会执行json.loads # app.config.from_mapping({'DEBUG': True}) @app.route('/') def index(): # return jsonify({'code': 100, 'msg': '成功'}) return 'hello' if __name__ == '__main__': app.run()
路由系统
from flask import Flask, jsonify app = Flask(__name__) # 1 flask 路由系统是基于装饰器的,但是它的本质是 add_url_rule # 2 装饰器的参数及作用 ''' 1 rule : 路径 2 methods: 可以允许的请求方式 3 endpoint:路由别名 ''' # 3 如果不用装饰器注册路由,需要使用 app.add_url_rule('/', 'index', index, methods=['GET']) # 4 详细研究:add_url_rule-->它的参数--》都可以给@app.route('/') ''' 1 rule, URL规则 2 view_func, 视图函数内存地址 3 defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}为函数提供参数 @app.route('/',defaults={name:lqz}) def index(name): pass 4 endpoint = None, 名称,用于反向生成URL,即: url_for('名称') 5 methods = None, 允许的请求方式,如:["GET", "POST"] 6 strict_slashes = None 对URL最后的 / 符号是否严格要求 @app.route('/index', strict_slashes=False) #访问http://www.xx.com/index/ 或http://www.xx.com/index均可 @app.route('/index', strict_slashes=True) #仅访问http://www.xx.com/index 7 redirect_to = None 重定向到指定地址 @app.route('/index/<int:nid>', redirect_to='/home/<nid>') ''' # @app.route('/') def index(): # return jsonify({'code': 100, 'msg': '成功'}) return 'hello' def login(): return 'login' app.add_url_rule('/', 'index', index, methods=['GET']) app.add_url_rule('/login', 'login', login) if __name__ == '__main__': app.run()
标签:02,index,return,flask,app,--,__,config From: https://www.cnblogs.com/wzh366/p/18040517