0


Python Flask开发笔记

Python Flask开发笔记

参考文档:https://dormousehole.readthedocs.io/en/latest/
https://flask.net.cn/

一、创建flask项目

1.开发环境:

操作系统:windows10
python版本:python-3.7.9
flask版本:flask-2.2.2

2.安装Flask

# 查看python版本 ==》 版本3.7.9
C:\Users\Administrators>python -v
    Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18)[MSC v.1900 64 bit (AMD64)] on win32
    Type"help","copyright","credits" or "license"for more information.
    import 'atexit'# <class '_frozen_importlib.BuiltinImporter'>
    >>> exit()# 安装flask
C:\Users\Administrators>python -m pip install flask==2.2.2

3.使用pycharm,创建flask项目

在这里插入图片描述
在这里插入图片描述

4. 项目布局

/home/user/Projects/flask-tutorial
├── flaskr/ --------------------------------- 项目根目录
│ ├── init.py
│ ├── db.py --------------------------------- 数据模型文件
│ ├── schema.sql
│ ├── auth.py --------------------------------- 用户认证文件(登录,注册等)
│ ├── blog.py --------------------------------- app程序入口文件
│ ├── templates/ --------------------------------- 模板文件目录
│ │ ├── base.html
│ │ ├── auth/
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ └── blog/
│ │ ├── create.html
│ │ ├── index.html
│ │ └── update.html
│ └── static/ --------------------------------- 静态文件目录
│ └── style.css
├── tests/ --------------------------------- 测试文件目录
│ ├── conftest.py
│ ├── data.sql
│ ├── test_factory.py
│ ├── test_db.py
│ ├── test_auth.py
│ └── test_blog.py
├── venv/ --------------------------------- 虚拟环境目录
├── setup.py --------------------------------- 安装文件
└── MANIFEST.ini ---------------------------------扩展库信息文件

二、flask介绍

1.介绍初始flask主程序接口文件

from flask import Flask  # 引用flask架构

app = Flask(__name__)# 创建Flask对象@app.route('/')# 路由分发defhello_world():# 接口函数return'Hello World!'# 返回的页面;返回的数据if __name__ =='__main__':
    app.run()# 运行flask

2.Flask() 类

1.Flask参数解释

# 必选参数
import_name: str,# 应用程序包的名称,通过它来拼接静态文件或者模板文件路径# 可选参数
static_url_path: t.Optional[str] = None,
static_folder: t.Optional[t.Union[str, os.PathLike]] = "static",  
static_host: t.Optional[str] = None,  
host_matching: bool = False, 
subdomain_matching: bool = False,
template_folder: t.Optional[str] = "templates",
instance_path: t.Optional[str] = None,
instance_relative_config: bool = False,
root_path: t.Optional[str] = None,

0.sys.modules用于缓存程序导入模块名

程序在导入某个模块时,会首先查找sys.modules中是否包含此模块名,若存在,则只需将模块的名字加入到当前模块的Local名字空间中;若不存在,则需要从sys.path目录中按照模块名称查找模块文件,

1.import_name 主程序模块名

app = Flask(import_name=__name__)print('is __name__ %s'% __name__)print(app.import_name,'ssss')
输出:
is __name__ app
app ssss
# 通过sys.modules.get(import_name) 获取模块的路径

2.static_url_path 浏览器url访问路径

如果

static_url_path=/test/url/

浏览器访问:

https://127.0.0.1:8080/test/url/js/index.js
static_url_path=None

浏览器访问:

https://127.0.0.1:8080/js/index.js

3.static_folder 静态文件存储目录

如js,css,图片等文件存储目录,浏览器访问时,如果static_url_path 存在,加上该url+文件名,浏览器访问:

https://127.0.0.1:8080/static_url_path路径/js/index.js


如果static_url_path 不存在 浏览器访问:

https://127.0.0.1:8080/js/index.js

4.static_host 静态文件主机地址

指定主机与host_matching=True一起使用才有效

5.host_matching

当host_matching=True时,须指定static_host=主机地址:端口号,默认localhost:5000

6.template_folder 模板存储目录

一般存储

.html

等页面文件

7.instance_path 指定配置文件存储目录

instance_path和instance_relative_config是配合来用的、
这两个参数是用来找配置文件的,当用

app.config.from_pyfile('settings.py')

这种方式导入配置文件的时候会用到
实例文件夹与默认的跟文件夹分离,降低耦合度。方便后期修改实例的时候不影响到跟文件夹

from flask import Flask

app = Flask(__name__)print(app.instance_path,'instance_path')print(app.root_path,'root_path')
输出:
D:\PersonalProject\FlaskProject\test01\instance instance_path
D:\PersonalProject\FlaskProject\test01 root_path
# 根目录与实例目录只多了\instance# 实例:指定配置文件路径from flask import Flask
import os
settings_dir = os.path.dirname(os.path.abspath(__file__))#获取当前文件所在目录

app = Flask(__name__, instance_path=settings_dir+'/conf/', instance_relative_config=True)# instance_path指定配置文件目录(必须是绝对路径),instance_relative_config启用相对路径配置文件目录,instance_path和instance_relative_config一般一起使用print(app.auto_find_instance_path())print(app.instance_path)

app.config.from_pyfile('settings.py')print(app.config)
输出:
D:\PersonalProject\FlaskProject\test01\instance
D:\PersonalProject\FlaskProject\test01/conf/<Config {'ENV':'production','DEBUG':True,'TESTING':False,...}>

在这里插入图片描述

8.instance_relative_config

  1. instance_relative_config=True告诉应用配置文件是相对于 instance folder 的相对路径。实例文件 夹在 flaskr 包的外面,用于存放本地数据(例如配置密钥和数据 库),不应当提交到版本控制系统
  2. 与instance_path 一起使用,当为True时,会在instance_path指定的目录中查找配置文件,默认是在根目录下查找

9.root_path 项目的根目录

Flask类

root_path: t.Optional[str] = None

Flask继承自Scaffold类,Scaffold类构造函数中root_path, 是调用

get_root_path(self.import_name)

;如下代码:

if root_path isNone:
       root_path = get_root_path(self.import_name)

get_root_path(import_name: str)

defget_root_path(import_name:str)->str:
    mod = sys.modules.get(import_name)#模块路径对象; sys.modules是获取系统modules的路径如:{'app': <module 'app' from 'D:\\PersonalProject\\FlaskProject\\test01\\app.py'>}if mod isnotNoneandhasattr(mod,"__file__")and mod.__file__ isnotNone:return os.path.dirname(os.path.abspath(mod.__file__))
    loader = pkgutil.get_loader(import_name)if loader isNoneor import_name =="__main__":return os.getcwd()# 用于返回当前工作目录D:\PersonalProject\FlaskProject\test01ifhasattr(loader,"get_filename"):
        filepath = loader.get_filename(import_name)# type: ignoreelse:__import__(import_name)
        mod = sys.modules[import_name]
        filepath =getattr(mod,"__file__",None)if filepath isNone:raise RuntimeError("No root path can be found for the provided module"f" {import_name!r}. This can happen because the module"" came from an import hook that does not provide file"" name information or because it's a namespace package."" In this case the root path needs to be explicitly"" provided.")return os.path.dirname(os.path.abspath(filepath))

3.Config类及配置参数含义

这是flask基础配置Config类

"ENV":None,"DEBUG":None,# 是否开启debug模式,如果代码有修改随时自动重启"TESTING":False,# 是否开启测试模式"PROPAGATE_EXCEPTIONS":None,# 异常传播(是否在控制台打印日志log),当debug或testing开启,自动为true"SECRET_KEY":None,# 在启用session时,一定会使用它"PERMANENT_SESSION_LIFETIME": timedelta(days=31),# session的生命周期,默认为31天"USE_X_SENDFILE":False,#是否弃用x_sendfile"SERVER_NAME":None,# 服务器访问域名"APPLICATION_ROOT":"/",# 项目完整路径"SESSION_COOKIE_NAME":"session",# 在cookie中存放session时的key"SESSION_COOKIE_DOMAIN":None,"SESSION_COOKIE_PATH":None,"SESSION_COOKIE_HTTPONLY":True,"SESSION_COOKIE_SECURE":False,"SESSION_COOKIE_SAMESITE":None,"SESSION_REFRESH_EACH_REQUEST":True,"MAX_CONTENT_LENGTH":None,# 如果设置为字节数,flask会拒绝内容长度大于此值的请求进入,并返回“413”状态码"SEND_FILE_MAX_AGE_DEFAULT":None,"TRAP_BAD_REQUEST_ERRORS":None,"TRAP_HTTP_EXCEPTIONS":False,"EXPLAIN_TEMPLATE_LOADING":False,"PREFERRED_URL_SCHEME":"http","JSON_AS_ASCII":None,"JSON_SORT_KEYS":None,"JSONIFY_PRETTYPRINT_REGULAR":None,"JSONIFY_MIMETYPE":None,"TEMPLATES_AUTO_RELOAD":None,"MAX_COOKIE_SIZE":4093,

4.url_for()

test_request_context() 告诉 Flask 正在处理一个请求,而实际上也许我们正处在交互 Python shell 之中, 并没有真正的请求

@app.route('/')defindex():return'index'@app.route('/login/')@app.route('/login/<name>')deflogin(name):returnf'{name} login '@app.route('/user/<username>')defprofile(username):returnf'{username}\'s profile'with app.test_request_context():print(url_for('index'))print(url_for('login', name='userl',next='/'))print(url_for('login',next='/'))print(url_for('profile', username='John Doe',next='/user/jacky', t='ddddd'))# 如上 url_for()第一个参数:路由处理函数名,如果关键字参数在路由中存在静态数据,如果不存在就是动态数据# /user/John Doe?next=/user/jacky&t=ddddd  # %20表示空格,%2F表示/
结果:
//login/userl?next=%2F
/login/?next=%2F
/user/John%20Doe?next=%2Fuser%2Fjacky&t=ddddd

三、数据模型

1. 数据模型

import os
from flask import make_response
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

# 配置文件目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
INSTANCE_PATH = os.path.join(BASE_DIR,'conf')
app = Flask(__name__, instance_path=INSTANCE_PATH, instance_relative_config=True)
app.config.from_pyfile('live.py')
db = SQLAlchemy(app)# 创建SQL关联对象
migrate = Migrate(app, db)# 创建迁移对象classUser(db.Model):# 数据模型
    __tablename__ ='user'id= db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, index=True)
    password = db.Column(db.String(128))@app.route('/')defhello_world():# put application's code hereprint("服务器接收了这次请求")# 对数据的操作
    user = User(email='2232323', password='qaz123', job='student')
    db1.session.add(user)
    db1.session.commit()
    
    response = make_response("hello world")
    response.headers["Access-Control-Allow-Origin"]="http://127.0.0.1:8000"# 服务器告诉浏览器,允许5000端口进行数据传输。return response
if __name__ =='__main__':
    app.run()

2. 执行迁移命令

(py39_env)PS D:\PersonalProject\FlaskProject\test01>flask db init # 数据库初始化
    Creating directory D:\PersonalProject\FlaskProject\test01\migrations ...  done
    Creating directory D:\PersonalProject\FlaskProject\test01\migrations\versions ...  done
    Generating D:\PersonalProject\FlaskProject\test01\migrations\alembic.ini ...  done
    Generating D:\PersonalProject\FlaskProject\test01\migrations\env.py ...  done
    Generating D:\PersonalProject\FlaskProject\test01\migrations\README ...  done
    Please edit configuration/connection/logging settings in 'D:\\PersonalProject\\FlaskProject\\test01\\migrations\\alembic.ini' before proceeding.(py39_env)PS D:\PersonalProject\FlaskProject\test01>flask db migrate # 数据库迁移
    INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
    INFO  [alembic.runtime.migration] Will assume transactional DDL.
    INFO  [alembic.autogenerate.compare] Detected added table 'user'
    INFO  [alembic.autogenerate.compare] Detected added index 'ix_user_email' on '['email']'
    Generating D:\PersonalProject\FlaskProject\test01\migrations\versions\544120ec4ede_.py ...  done
# 假设模型类新加减字段,执行次命令进行数据更新(py39_env)PS D:\PersonalProject\FlaskProject\test01>flask db upgrade # 数据库更新
    INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
    INFO  [alembic.runtime.migration] Will assume transactional DDL.
    INFO  [alembic.runtime.migration] Running upgrade  -> 544120ec4ede, empty message

3. 数据库的增删改查

# 增加一条记录
user = User(email='2232323', password='qaz123', job='student')
db1.session.add(user)
db1.session.commit()# 查找数据
users = User.query.all()print(users)

user = User.query.filter(User.id==1).first()print(user)

user = User.query.get(5)# 如果查找该id记录不存在返回Noneprint(user)

4. 查询条件语句

与(and_)

userdd = User.query.filter(User.name.startswith("2"),User.email.startswith("2")).all()print(userdd)

userdd = User.query.filter(and_(User.name.startswith("2"),User.email.startswith("2"))).all()print(userdd)

非(!= / not_)

notpwd = User.query.filter(User.pwd!="qaz123").all()# 最常用print(notpwd)

notpwd = User.query.filter(not_(User.pwd=="qaz123")).all()print(notpwd)

或(or_)

user = User.query.filter(or_(User.password =="qaz123",User.email.startswith("2"))).all()print(user)

四、模版

@app.route('/')defhello_world():  
    response = render_template("index.html")# 返回一个html页面return response

@app.route('/')defhello_world():  
    user = User.query.get(1)
    response = render_template("index.html", user=user)# 向前端传递数据return response
@app.route('/')defhello_world():  
    user = User.query.get(1)
    context ={"user": user
    }
    response = render_template("index.html",**context)# 向前端传递数据return response
标签: python flask 后端

本文转载自: https://blog.csdn.net/chenliang1038/article/details/128578341
版权归原作者 Jacky-008 所有, 如有侵权,请联系我们删除。

“Python Flask开发笔记”的评论:

还没有评论