# flaskdev **Repository Path**: playertk/flaskdev ## Basic Information - **Project Name**: flaskdev - **Description**: No description available - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-02-20 - **Last Updated**: 2021-08-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: 学习 ## README ``` flaskdev ├─ apps #模块目录 │ ├─ __init__.py #Apps模块init │ ├─ templates #模板目录 │ │ └─ user #模块对应的模板目录 │ ├─ static #静态页面目录 │ │ └─ css │ └─ user │ ├─ __init__.py #user模块init │ ├─ model.py #模型模块 │ └─ view.py #视窗模块 ├─ exts #额外工具模块 │ └─ __init__.py #额外工具模块init ├─ config.py #flask参数配置模块 └─ run.py #主入口 ``` ## 路由 ### 1.路由的写法 通过route绑定自定义URL ```python @app.route('/index') def index(): return '' ``` 实际内部实现 是使用了add_url_rule()函数实现 ```python def index(): return '' app.add_url_rule('/index', view_func=index) ``` 结果一致,均为结果URL: http://192.168.1.10:8080/index ### 2.路由的变量规则 通过把URL的一部分标记为***variable_name***就可以在URL中添加变量。 标记的部分会作为关键字参数传递给函数。 通过使用***converter:variable_name***,可以选择性的加上一个转换器,为变量指定规则。 **string**(缺省值) 接受任何不包含斜杠的文本 **int** 接受正整数 **float** 接受正浮点数 **path** 类似string 但是可以包含斜杠 **uuid** 接受UUID字符串 ### 3.上下文相应 ### request请求分类: #### get请求 request.args.get("key") 获取get请求参数 访问时会在地址栏直接显示参数不安全,且参数大小比较小。 #### post请求 参数不显示在地址栏,一般用户注册、登录都通过post请求完成。 request.form.get("key", type=str, default=None) 获取表单数据 request.values.get("key") 获取所有参数 本文主要介绍以上三种方式,其次也有获取解析json数据格式,request.get_json() request.files['file'] 获取上传的文件组到服务器 ### 4. 视图函数 视图函数分类: 1.redirect() 2.render_template() 3.make_response() ## UUID版本选择 ###UUID编码格式 UUID 的十六个八位字节被表示为 32个十六进制数字,以连字号分隔的五组来显示,形式为 8-4-4-4-12, 总共有 36个字符(即三十二个英数字母和四个连字号)。例如: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx 数字 M的四位表示 UUID 版本,当前规范有5个版本,M可选值为1, 2, 3, 4, 5 ; 数字 N的一至四个最高有效位表示 UUID 变体( variant ), 有固定的两位10xx因此只可能取值8, 9, a, b UUID版本通过M表示,当前规范有5个版本, M可选值为1, 2, 3, 4, 5。这5个版本使用不同算法,利用不同的信息来产生UUID,各版本有各自优势,适用于不同情景。具体使用的信息 ###总结 从UUID的不同版本可以看出,Version 1/2适合应用于分布式计算环境下,具有高度的唯一性; Version 3/5适合于一定范围内名字唯一,且需要或可能会重复生成UUID的环境下;至于Version 4, 个人的建议是最好不用(虽然它是最简单最方便的)。通常我们建议使用UUID来标识对象或持久化数据, 但以下情况最好不使用UUID:映射类型的对象。比如只有代码及名称的代码表。人工维护的非系 统生成对象。比如系统中的部分基础数据。对于具有名称不可重复的自然特性的对象,最好使用 Version 3/5的UUID。比如系统中的用户。如果用户的UUID是Version 1的,如果你不小心删除了 再重建用户,你会发现人还是那个人,用户已经不是那个用户了。(虽然标记为删除状态也是一种解决方案, 但会带来实现上的复杂性。) ## 蓝图模式 蓝图是路由的另一种表现方式,蓝图类似路由的中间件,形成app和路由之间的一个缓冲区域。 ## 模板 网页 ==》 模板引擎处理 ---》 模板 render_template ### 常用语法与标识 **{{ 变量 }}** **{% if 条件 %} {% endif %}** **for, block marco,with** **{% extends '' %}** **{% include '' %}** **{% import '' %}** **{% set username = '' %}** ## Flask-script ### 加壳以后需要在添加一个命令才能执行 例如 python run.py runserver optional arguments: -?, --help         show this help message and exit -h HOST, --host HOST -p PORT, --port PORT --threaded --processes PROCESSES --passthrough-errors -d, --debug       enable the Werkzeug debugger (DO NOT use in productioncode) -D, --no-debug      disable the Werkzeug debugger -r, --reload       monitor Python files for changes (not 100% safe forproduction use) -R, --no-reload     do not monitor Python files for changes --ssl-crt SSL_CRT    Path to ssl certificate --ssl-key SSL_KEY    Path to ssl key ### 自定义启动命令 ```python @manager.command def init(): print("初始化") ``` **自定义一个命令才能执行 例如 python run.py init** ## 数据库 pymysql: 提供底层驱动 让python和数据库有一个通信桥梁 SQLAlchemy: ORM.实现python类到数据库的映射关,无需使 用数据库指令进行增删改查 flask-sqlalchemy:基于SQLAlchemy,做了提升 使得程序员在开发的时候更加方便 flask-migrate:用于实现映射的命令集 **(关于flask与数据库模型创建流程,请参考教程P18_5.2flask之模型简介和配置视频)** ### 常见的数据类型: Interger     整型 String(size)    字符串类型,务必指定大小 Text       长文本类型 DateTime    日期时间 Float       浮点类型 Boolean     布尔类型 PickleType    存储pickle类型 主要跟序列化有关 LargeBinary   存储大的二进制类型 ### 可选的: primary_key=True   主键 autoincrement=True  自增 nullable=False     不允许为空 unique=True     唯一 default=datetime.now 默认值 设置当前记录时间 ### 步骤 1. 配置数据库的连接路径 mysql + pymysql://user:password@hostio:port/Database_name SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:root@127.0.0.1:3306/' 2. 关联SQLAlchemy映射(ORM映射) ```python from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() ... def create_app(): app = Flask(__name__) ... db.init_app(app) # 将你的flask对象与SQLAlchemy功能关联 ... return app ... ``` 3. migrate 添加 额外的命令功能 ```python Migrate(app=app, db=db) # 让Migreate影响数据库映射 manager.add_command('db', MigrateCommand) # 给Manager添加管理命令 ``` 4. 创建数据库模型 (ORM映射) model.py **(用类的形式创建数据库表,然后通过指令去执行数据库建表功能的自动化工作))** ```python class User(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) #autoincrement 自增加 username = db.Column(db.String(15), nullable=False) #‘nullable=False’ 不可空置 password = db.Column(db.String(12), nullable=False) phone = db.Column(db.String(11), unique=True) #‘unique=True’数据唯一 register_time = db.Column(db.DateTime, default=datetime.utcnow) def __str__(self): return self.username ``` 5. 使用命令 a. 在 app.py 中导入模型:frome apps.user.models import User b. run.py db init 创建migrations目录 c. run.py db migrate 创建模型映射在数据库建表工具 **(创建数据库后若重新初始化,须删除数据库里alembic_version 版本号对应内容)** d. run.py db upgrade 执行工具指令创建数据库表 **(关于flask与数据库模型创建流程,请参考教程P18_5.2flask之模型简介和配置视频)** 6. 数据库查询: 查询所有: 模型类.query.all() ~ select * from user; 如果有条件查询: ```python 模型类.query.filter_by(字段名 = 值) ``` select * from user where 字段=值 ```python 模型类.query.filter_by(字段名 = 值).first() ``` select * from user where 字段=值 limit ```python 模型类.query.filter() ``` 需要的参数是一个布尔值判断参数 支持数值比较判断时间比对判断比较大小 ```python 模型类.query.filter().first() ``` 返回搜索的第一个符合条件的对象 ```python 模型类.query.filter_by() ``` 需要传递的是一个数据比对参数 ```python 模型类.query.filter(User.username.endswith('p')).all() ``` select * from user where username like '%p' 寻找所有包含字母“p”结尾的对象集合 ```python 模型类.query.filter(User.username.startswith('p')).all() ``` select * from user where username like '%p' 寻找所有包含字母“p”开头的对象集合 ```python 模型类.query.filter(User.username.like('p%')).all() ``` select * from user where username like '%p' 寻找所有包含字母“p”开头的对象集合 ```python 模型类.query.filter(User.username.contains('p')).all() ``` select * from user where username like '%p%' 寻找所有包含字母“p”的对象集合 ```python 模型类.query.filter(or_(User.username.like('p%'), User.username.contains('i'))).all() ``` select * from user where username like 'p%' or username like '%i%' 寻找所有包含字母“p”或者包含字母"i"的对象集合 7. 数据库删除: #### 逻辑删除 ```python User.isdelete = True # 被标记的数据被查询的时候会被过滤掉 db.session.commit() ``` ```python # 查询的时候加上过滤,可以排除逻辑删除的数据 users = User.query.filter(User.isdelete == False).all() ``` #### 物理删除 ```python db.session.delete(user) db.session.commit() ``` 8. 数据库表一对多关系关系建立: 常见对应关系:班级对学生、学校对班级、公司对员工; #### 综述:如何在Flask框架中体现1对多的模型关系? #### 具体方法: #### 可以使用ForignKey()方法在“多对象”上添加外键,建立与“一对象”的对应关系。 #### relationship()方法均可添加在 “一对象”或者“多对象”上, 只是注意如果添加在“一对象”上,则返回的是“多对象”列表, #### 需要使用for递归来获取单个对象。 #### ForignKey是给表实现映射关系的,relationship()则是给模板使用 (1).建立数据表外键: 这里通过建表关系来实现各个表之间的对于关系 ```python # 'article/model.py' class Article(db.Model): user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) ``` (2).建立逆向查询关系语句: 这里是在查询层面建立flask反向查询的步骤, ```python # 'user/model.py' class User(db.Model): # 增加一个文章索引字段 # 'select'(默认值)就是说SQLAlchemy会使用一个标准的select语句必要时一次加载数据。 # 'joined'告诉SQLAlchemy使用JOIN语句作为父级在同一查询中来加载关系。 # 'subquery'类似'joined' ,但是SQLAlchemy会使用子查询。 # 'dynamic'在有多条数据的时候是特别有用的。不是直接加载这些数据, # SQLAlchemy 会返回一个查询对象,在加载数据前您可以过滤(提取)它们。 articles = db.relationship('Article', backref='user', lazy='select') ``` (3).使用查询语句: (1).使用外键表查询相关数据: (只多查一)在知道有外键表的数据查询其对应主键表数据的方法 ```html {% for article in articles %}

{{ article.title }}

作者:{{ article.user.username }}

{{ article.content }}

{{ article.p_datetime }}
{% endfor %} ``` (2).使用主表查询多关系数据: (只一查多)在获得主表数据,查询其他与其有多关系表的数据 ```html {% for article in user.articles %}

{{ article.title }}

作者:{{ user.username }}

{{ article.content }}

{{ article.p_datetime }}
{% endfor %} ``` 9. 数据库表多对多关系关系建立: 常见对应关系:用户对商品、学生对课程; #### 综述:如何在Flask框架中体现多对多的模型关系? #### 通过创建关系表将2个独立表的多对多关系记录下来 #### 外键写在关系表中,通过ForignKey()方法在关系表中声明 #### relationship()方法写的在独立表上,注意不是写在关系表上!!! ### 加密 密码加密 常用的md5 加密数据通常是 32位、40位、64位、128位 所以在创建数据库的时候要提供足够的数据长度 ```python import hashlib msg = 'hello wold' md5 = hashlib.md5(msg.encode('utf-8')) print(md5) #这里只是一个哈希对象 r = md5.hexdigest() #需要吧对象值转成16进制的数据 print(r) sha1 = hashlib.sha1(msg.encode('utf-8')).hexdigest() print(sha1) ```