【Flask】从手工测试到测试开发
一、 安装
pip install flask
app.config.from_object("Settings.ProductionConfig") # ↓
# Settings.py class Baseconfig(object): DEBUG = False TESTING = False DATABASE_URI = 'sqlite://:memory' class ProductionConfig(BaseConfig): DATABASE_URI = 'mysql://user@pre/foo' class DevilopmentConfig(BaseConfig): DEBUG = True DATABASE_URI = 'mysql://user@dev/foo' class TestingConfig(BaseConfig): TESTING = True DATABASE_URI = "mysql://user@test/foo"
flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为: { '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), 'USE_X_SENDFILE': False, 'LOGGER_NAME': None, 'LOGGER_HANDLER_POLICY': 'always', 'SERVER_NAME': None, 'APPLICATION_ROOT': None, 'SESSION_COOKIE_NAME': '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, }
from flask import Flask app =Flask(__name__) @app.route("/index",method=["GET"]) def demon(): return "hello world" if __name__ == "__main__": app.run()
路由-创建路由的两种方式
# 方法一 建议 from flask import Flask app = Flask(__name__) @app.route("/index",methods=["GET"]) def demon(): return "hello world" if __name__ == "__main__": app.run()
# 方法二 from flask import Flask app = Flask(__name__) def demon(): return "hello world" app.add_url_rule("/index",view_func=demon) if __name__ == "__main__": app.run()
2.反向url -- url_for
# 相当于是取别名,用于重定向时,url过长 from flask import Flask,url_for app = Flask(__name__) @app.route("/index",methods=["GET"],endpoint= "n1") def demon(): return "hello world" @app,route("/page",methods=["GET"]) def page(): new_url = url_for('n1') # 使用别名 new_url2 = url_for("index") #直接使用函数名 return "page" if __name__ == "__main__": app.run()
3.路由转换器
@app.route("/index/<int:nid>") # 指定为int类型 def index(nid): return nid @app.route("/index/<username>") # 默认是字符串 @app.route("/index/<float:nid>") # 浮点类型 @app.route("/index/<path:path>") # 默认是字符串
4.自定义转换器
from flask import Flask app = flask("demo") class RegexConverter(BaseConverter): """ 自定义URL匹配正则表达式 """ def __init__(self,map,regex): super(RegexConverter,self).__init__(map) self.regex = regex def to_python(self,value): return int(value) def to_url(self,value): val = super(RegexConverter,self).tu_url(value) return val app.url_map_conserters['regex']= RegexConverter # regex 名字是自定义,即在使用时的名称 @app.route("/index/<regex("\d+"):nid>",methods=["GET"]) def index(): return "index"
5.url 重定向
from flask import Flask app = Flask("demo") @app.route("/v1/login",methods=["POST"],redirect="/v2/login") def old_login(): return "hello old" @app.route("/v2/login",method=["POST"]) def new_login(): return "hello new"
6.装饰器
# 在视图中添加装饰器 from flask import Flask import functools def warper(func): @functools.wraps(func): # 将被装饰的函数名返回给装饰器 def inner(*args,**kwargs) return func(*args,**kwargs) return inner app = Flask("test") @app.route("/index") @warper # 自定义装饰器需要写在路由装饰器下面,否则只会装饰一次 def index(): return "index" @app.route("/login") @warper def login(): return "login" if __name__ == "__main__": app.run() # 视图函数中,如果只有一个函数被装饰,则可以不使用functools装饰,因为不会重名 #AssertionError: View function mapping is overwriting an existing endpoint function: inner
7.视图 - CBV 、FBC
-
CBV :以类形式实现视图函数
-
# CBV from flask import Flask from flask import views app = Flask(__name__) class IndexView(views.View) methods = ["GET"] decorators = [warper,] # 给类中所有的函数加个装饰器 def despatch_request(self): # 反射函数,需要自己去实现 return "index" app.add_url_rules("/index",view_func=IndexView.as_view(name='index')) # 第二种 根据不同的请求类型,访问post、get from flask import views class IndexView2(views.MethodView): # 已经实现好了despatch_request反射函数,无需自己去实现 methods = ["GET"] decorators = [warper,] # 装饰器列表 def get(self): return "get" def post(self): return "post" app.add_url_rules("/index",view_func=IndexView.as_view(name='index'))
8.请求和响应
from flask import Flask from flask import request # 请求 from flask import render_template,redirect,make_response,jsonify # 响应 import json app = Flask("req") @app.route("/",methds=["GET","POST"]) def demo(): # 请求 res_args = request.args res_method = request.method res_form = request.form res_data = request.data res_json = request.json # json 格式数据 res_headers = request.headers res_url = request.url res_values = request.values res_file = request.files res_cookies = request.cookies # 需要创建templates文件夹,将静态文件放在里面 return render_template("xxx.html",name="name") return json.dumps({"":""}) return jsonify({"":""}) return "str" return redirect("/login") # 重定向 # 返回 response ,既可以返回内容,又可以设置响应头 response = make_response(render_template("xxx.html")) # response = make_response("str") response.set_cookie("key","value") response.headers["X-Someting"] ="A value" response.delete_cookie("key") return response
9.模板与jinja2语法
from flask import Flask,render_template app = Flask(__name__) # 服务器名称,template最好与之在同一文件夹下,否则会找不到模板文件 def render_input(name): return f"<input value='{name}'>" @app.route("/index") def index(): result ={ "ret":0, "data":{"id":1, "name":"alex", "age":15 "tags":[1,2,3] }, "obj":lambda i:i+1, "input":render_input } return render_template("index.html",**result) if __name__ == "__main__": app.run()
</head> <body> <h1>{{ret}}</h1> <h1>{{data}} {% for i in data.tags %} {% if i > 1 %} <h2>for循环取值 {{i}}</h2> {% endif %} {% endfor %} <p>直接通过索引取值 {{data.tags[0]}} {{data.tags.2}}</p> </h1> </body> </html>
#模板中返回函数
from flask import Flask,render_template,Markup app = Flask(__name__) # 服务器名称,template最好与之在同一文件夹下,否则会找不到模板文件 def render_input(name): return f"<input value='{name}'>" # 返回html 会防止xls攻击,返回的永远都是str,需要配合前端修改 # 3.1 以上改为 from markupsafe import Markup def render_dutton(name): return Markup(f"<input value='{name}'>") # 防止xls攻击,后端处理 @app.route("/index") def index(): result ={ "obj":lambda i:i+1, "input":render_input } return render_template("index.html",**result) if __name__ == "__main__": app.run()
</head> <body> <h1>{{obj(5)}}</h1> // 函数也可以传给前端,但不会自动执行,需要在前端代码中写入()执行 <h2>{{input("alex") | safe }}</h2> // 防止xls攻击, 需要使用 | safe </body> </html>
·全局模板
from flask import Flask,render_template app = Flask(__name__) @app.template_global() //全局模板函数装饰器 def add(a,b): return a+b @app.route("/index") def index(): return render_template("index.html") @app.route("/home") def home(): return render_template("index.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{add(1,2)}}</h1> </body> </html>
·模板继承
// 母板 templateA.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div>头部</div> <div>{% block content %} {% endblock%}</div> //待替换的类容 <div>底部</div> </body> </html>
// 继承 templateA.html模板 {% extends 'templateA.html'%} {% block content %} <h1>{{add(2,3)}}</h1> // 替换母板中的内容 {% endblock %}
10.特殊装饰器
# 视图函数执行前 from flask import Flask app = Flask(__name__) # before_request=["start1","start2"] @app.before_request def start(): print("视图函数执行前执行") # 视图函数指执行后 from flask import Flask app = Flask(__name__) # after_request=["endresponse2","endresponse1"] @app.after_request # 有多个的时候,会执行一个翻转的动作 def endresponse(response): return reaponse
# 实际使用 from flask import Flask app = Flask(__name__) @app.before_request def start(): print("视图函数执行前执行") @app.after_request def endresponse(response):// 必须要有返回值 return reaponse @app.route("/") def index(): return "视图函数" app.run()
# 自定义404 页面 from flask import Flask app = Flask(__name__) @app.before_first_request def start(): print("视图函数执行前执行,并且只执行一次") @app.errorhandler(404)
11.闪现
from flask import Flask,flash,get_flashed_messages app = Flask(__main__) # 将上一个接口的错误,返回到第二个接口显示 @app.route("/home") def home(): flash("这是闪现闪现") flash("这是分类",category="类名1") # 类似于队列 flash("这是分类",category="类名2") return "home" @app.route("/index") res =get_flashed_messages() x1= get_flashed_messages(category_firlter=["类名1"]) x2= get_flashed_messages(category_firlter=["类名2"]) return str(res)
12.中间件 middleware (很少用,可以用于用户ip黑名单)
from flask import Flask app = Flask(__main__) @app.route("/index") def index(): return "index" class Middleware(object): def __init__(self,old_wsgi_app): self.old_wsgi_app = old_wsgi_app def __call__(self,**args,**kwargs): print("在所有操作之前操作") obj = self.old_wsgi_app(**args,**kwargs) print("在所有操作之后操作") return obj if __name__ == "__main__": app.wsgi.app = Middleware(app.wsgi.app) app.run()
test_platform ——test_platform ————__init__.py ————templates ————views ————static ——manage.py
#init.py from flask import Flask app = Flask(__name__) from .views.admin import ad from .views.user import us app.register_blueprint(ad,url_prefix="/admin") # 给url加个前缀 app.register_blueprint(us)
#manage.py form test_platform import app app.run(debug=True)
# views/admin from flask import Blueprint ad = Blueprint("ad",__name__) # 单个类型中,加一个登录验证 @ad.before_request def login(): print("login") @ad.route('/index') def index(): return "index"
# views/user.py from flask import Blueprint from flask import render_template us = Blueprint("us",__name__) @us.route("/home") def home(): return render_template("home.html")
五、local
# local的实现原理(基于函数) # 相当于是线程锁 from threading import get_ident,Thread import time storage = {} def set(key,value): ident = get_ident() if ident in storage: storage[ident][key] = value else: storage[ident] = {key:value} # 通过线程的唯一标识,来定制自己的local def get(key): ident = get_ident() value = storage[ident][key] return value def task(arg): set("val",arg) time.sleep(2) v = get("val") print(v) for i in range(10): t = Thread(target = task ,arges = (i,)) t.start()
# local 面向对象实现 try: from greenlet import getcurrent as get_ident # 基于携程 except Exception as e: from threading import get_ident from threading import Thread import time class Local(object): def __init__(self): # self.storage = {} # 报错!原因: # 在构造函数执行前,会触发类本身的setattr方法,此时当前类本身没有self.storage变量, # 需要去父类创建一个内存空间,存放storage变量,此时还没有调用类本身的__setattr__ object.__setattr__(self,"storage",{}) def __setattr__(self, key, value): ident = get_ident() if ident in self.storage: self.storage[ident][key] = value else: self.storage[ident] = {key: value} def __getattr__(self, key): ident = get_ident() value = self.storage[ident][key] return value obj = Local() def task(arg): obj.val = arg time.sleep(2) print(obj.val) for i in range(10): t = Thread(target=task, args=(i,)) t.start()
六、
分为三个阶段 阶段一: 将ctx(request,session) 放到Local对象里面 阶段二: 视图函数导入 request/session 阶段三: 处理完毕后,将session保存到cookie, 将ctx删除
此处省略............ (待补充)
七、组件使用和原理
session
# 默认session from flask import Flask from flask import session app = Flask(__name__) app.secret_key = "app" @app.route("/index") def index(): session["X-Token"] = uuid.uuid4() return "index" @app.route("/home") def home(): uid = session.get("X-Token") return str(uid)
Redis session
# 安装flask_session : pip install flask_session from redis import Redis from flask_session import RedisSessionInterface app = Flask(__name__) app.session_interface = RedisSessionInterface( redis=Redis(host="127.0.0.1", port=6379), key_prefix="app" )
from flask import Flask from flask_session import Session from .apis.user_apis import us def create_app(): app = Flask(__name__) app.register_blueprint(us) app.config.from_object("settings.DevelopmentConfig") Session(app) # 将session 替换成redis session return app
# settings.py from datetime import timedelta from redis import Redis class Config(object): DEBUG = False SECRET_KEY = "suijizifuchuan" # 随机字符串 PERMANENT_SESSION_LIFETIME = timedelta(minutes=20) #session超时时间 SESSION_REFRESH_EACH_REQUEST = True SESSION_TYPE = "redis" class ProductionConfig(Config): SESSION_REDIS = Redis(host="192.168.0.94", port="6379") class DevelopmentConfig(Config): DEBUG = True SESSION_REDIS = Redis(host="localhost", port="6379") class TestingConfig(Config): DEBUG = True SESSION_REDIS = Redis(host="127.0.01", port="6379")
# views/apis.py from flask import Blueprint from flask import session us = Blueprint("us",__name__,url_prefix="/us") @us.route("/login") def login(): session["name"] = 12345 return "123" @us.route("/home") def home(): name = session.get("name") print(name) return "456"
原生 session中存储的是字典,修改字典内部元素时,会造成数据不更新的问题 # 方法一 motified = True # 方法二 SESSION_REFRESH_EACH_REQUEST = True session.permanent = True
数据库连接池
mysql 的操作
//: mysql -u root -p 123456 # 进入数据库
//: show databases; # 查看所有的数据库
# <?>中的表示该字段为自定义
//: create database <base_name> # 创建数据库
//: uer <base_name> # 进入数据库
//: show tables # 查看该数据库下所有的表
//: create table <table_name>(id int auto_increment primary key,name varchar(20),pwd varchar(64)); # 创建表结构
//: insert into <table_name>(name,pwd) values("alex","123456") # 插入数据
//: select * form <table_name> # 查询数据
pymsql 的应用
# pip install pymysql import pymysql conn = pymysql.connect( host="localhost", user="root", password="123456", database="flask_test" ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 返回数据为字典格式 cursor.execute("select * from user") result = cursor.fetchone() cursor.close() conn.close() print(result.get("id"))
DBUtils
//安装 pip install DBUtils # utils/pool.py from dbutils.pooled_db import PooledDB import pymysql POOL = PooledDB( creator=pymysql, # 使用连接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制 mincached=2, # 初始化时,连接池中至少创建的空闲连接,0表示不创建 maxcached=5, # 连接持中,最多闲置的连接,0和None不限制 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待,True/False maxusage=None, # 一个链接池最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如["set datestyle to ...","set time zone ..."] ping=0, # ping Mysql服务器,检查服务是否可用0-7,一般使用0,4,7 0 不检查,4 执行查询时,7 执行所有操作时 host="127.0.0.1", port=3306, user='root', password="1234566", database="db_name" )
# settings.py from datetime import timedelta from redis import Redis class Config(object): DEBUG = False SECRET_KEY = "suijizifuchuan" # 随机字符串 PERMANENT_SESSION_LIFETIME = timedelta(minutes=20) #session超时时间 SESSION_REFRESH_EACH_REQUEST = True SESSION_TYPE = "redis" PYMSQL_POOL = PooledDB( creator=pymysql, host="127.0.0.1", port=3306, user='root', password="1234566", database="db_name" ) class ProductionConfig(Config): SESSION_REDIS = Redis(host="192.168.0.94", port="6379") class DevelopmentConfig(Config): DEBUG = True SESSION_REDIS = Redis(host="localhost", port="6379") class TestingConfig(Config): DEBUG = True SESSION_REDIS = Redis(host="127.0.01", port="6379")
# utils/sql.py import pymysql from flask import current_app class SQLHelper(object): @staticmethod def open(): POOL = current_app.config["PYMSQL_POOL"] conn = POOL.connection() cursors = conn.cursors(cursors=pymysql.cursors.DictCursor) return conn,cursors @staticmethod def close(conn,cursors): conn.close() cursors.close() @classmethod def fetch_one(cls,sql,args): conn,curso = cls.open() cursors.execute(sql,args) res = cursors.fetchone() cls.close(conn,cursors) return res @classmethod def fetch_all(cls,sql,args): conn,cursors = cls.open() cursors.execute(sql,args) res = cursors.fetchall() cls.close(conn,cursors) return res
# views/apis from ..utils.sql import SQLHelper obj = SQLHelper.fetchone("select * from user where name=%s and pwd =%s",[name,pwd])
# 安装 pip install weforms # /views/apis.py from ..modules.wt_verify import LoginForm @us.route("/sign", methods=["GET", "POST"]) def sign(): if request.method == "GET": form = LoginForm() return render_template("sign.html", form=form) form = LoginForm(formdata=request.form) if form.validate(): return render_template("sign.html", form=form.data) else: return render_template("login.html", form=form)
# /moudles/user_data_mgr.py fetch_one("select * from user where name = %(user)s and pwd =%(pwd)s", form.data) # 数据库支持字典数据
# /templates/sign.html {% extends "login.html" %} {% block login %} <form method="post" action="/us/sign"> {{ form.name }} {{ form.name.errors[0] }} {{ form.pwd }} {{ form.pwd.errors[0] }} <input type="submit" value="注册"> </form> {% endblock %}
# /modules/wt_verify.py from wtforms import Form from wtforms.fields import simple from wtforms import validators from wtforms import widgets class LoginForm(Form): name = simple.StringField( label='用户名', validators=[ validators.DataRequired(message='用户名不能为空.'), validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) pwd = simple.PasswordField( label='密码', validators=[ validators.DataRequired(message='密码不能为空.'), validators.Length(min=8, message='用户名长度必须大于%(min)d'), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}",message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} ) # https://www.cnblogs.com/wupeiqi/articles/8202357.html
MySQL-Python mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] MySQL-Connector mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> cx_Oracle oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
模板生成:sqlacodegen mysql+pymysql://niu_shop:Mogo2023@rm-wz97g2c8d2vvu7186fo.rwlb.rds.aliyuncs.com:3306/niu_shop --tables tab1,tab2.. > outfile
# 创建表
from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Integer, Index, String, Column Base = declarative_base() class Mytest(Base): __tablename__ = "user" id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(64), nullable=True,unique=True) pwd = Column(String(64),nullable=True) def init_db(): engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/flask_test') Base.metadata.create_all(engine) if __name__ == '__main__': init_db()
# 创建表外键、联合索引 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, UniqueConstraint, Index, ForeignKey from sqlalchemy import create_engine Base = declarative_base() class UserManagement(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32)) extra = Column(String(16)) class UserInfos(Base): __tablename__ = "userinfo" id = Column(Integer, primary_key=True, autoincrement=True) user_key = Column(String(32), unique=True, nullable=True) # 不能重复,不能为空 age = Column(Integer) sex = Column(String(16)) user_id = Column(Integer, ForeignKey("users.id")) # 创建外键 class Hobby(Base): __tablename__ ="hobby" id = Column(Integer,primary_key=True) caption = Column(String(50),default="篮球") class User2Hobby(Base): __tablename__ = "user2hobby" id = Column(Integer,primary_key=True,autoincrement=True) uid =Column(Integer,ForeignKey("userinfo.id")) hobby_id = Column(Integer,ForeignKey("hobby.id")) __table_args__ =( UniqueConstraint("uid","hobby_id",name="uix_uid_hobby_id"), # 联合唯一索引 ) def init_db(): engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/flask_test", echo=True) Base.metadata.create_all(engine)
增
from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine import modules engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/flask_test") maker = sessionmaker(bind = engine) session = maker() # 增加单条 obj = modules.User(name="alex",pwd="123456") session.add(obj) # 增加多条 session.add_all([ modules.User(name="alex",pwd="123456"), modules.User(name="alex1",pwd="1234567") ]) session.commit() # 每次增加后,需要commit一次 session.close()
查
from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine import modules engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/flask_test") maker = sessionmaker(bind = engine) session = maker() # 查询所有 result =session.query(User).all() for item in result: print(item.name,item.pwd)
from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Integer, Index, String, Column, ForeignKey from sqlalchemy.orm import sessionmaker Base = declarative_base() engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/flask_study') class db(object): def __init__(self): maker = sessionmaker(bind=engine) self.session = maker() def add(self): obj = User(name="alex2", pwd="123456") self.session.add(obj) self.session.commit() def select(self): result = self.session.query(User).all() # 查询所有 result = self.session.query(User).filter(User.name == 'alex') # 精确查询 result = self.session.query(User).filter(User.name.like('%alex%')) # 模糊查询 result = self.session.query(User).filter(User.name !='alex1') # 不包含 result = self.session.query(User).filter(User.name.in_(['alex1','alex'])) # 包含多个 result = self.session.query(User).filter(User.name.in_( self.session.query(Info.name).filter(User.name.like('%1%')) )) # 多层过滤 result = self.session.query(~User.name.in_(["alex1","alex2"])) # 不包含多个 result = self.session.query(User.name == None) # 为空 result = self.session.query(User.name != None).first() # 不为空 print(result.name) # 去一条 from sqlalchemy import and_, or_ # and 查询 result = self.session.query(User).filter(and_(User.name.like("%alex%"), ~User.name.like("%1%"))) # or 查询 result = self.session.query(User).filter(or_(User.name.like("%2%"),User.name.like("%1%"))) for item in result: print(item.name) print(item.pwd) from sqlalchemy import select stmt =select(User).where(User.name.in_(["2","1"]))
# sqlalchemy的select 函数查询 from sqlalchemy import select from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import Session engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/flask_study') session =Session(bind=engine) stmt =select(User).where(User.name.in_(["2","1"])) for info in session.scalars(stmt): print(info)
# 修改 from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.engine import create_engine Base = declarative_base() engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/flask_study') maker = sessionmaker(bind=engine) session = maker() session.query(User).filter(User.name =="alex").update({"name":"yl","pwd":123456}) session.commit() session.close()
# 删除 from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.engine import create_engine Base = declarative_base() engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/flask_study') maker = sessionmaker(bind=engine) session = maker() session.query(User).filter(User.id > 3).delete() session.commit()
1. 自动生成requirements.txt
pippreqs : 自动在项目中找依赖的环境及版本 root//#: pip3 install pippregs 切到项目目录下,执行 pipregs ./ 会生成一个requirements.txt 文件 pipregs ./ --force 覆盖原来的文件 pip install -r requirements.txt
2.函数与方法的区别
class Foo(object): def fatch(self): pass Foo.fatch(123) # 如果通过类去调用时,它就是方法 obj = Foo() obj.fathc() # 如果通过对象去调用时,它就是函数
3.域名与url的对应关系
@ c:\winodws\system32\etc\hosts 一一一一一一一一一一一一一一一一一一一一一一一一一一一一一 127.0.0.1:5000 www.baidu.com 127.0.0.1:5000 www.index.cn
4.uuid 生成唯一id
import uuid iid = uuid.uuid4()