【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,
    }

 

三、 应用

 1.路由

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 :以类形式实现视图函数

  • FBV :以函数形式,实现视图 (使用更为广泛)

# 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()
防止xls攻击,前端 | safe
</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"
)

  session redis 通过配置应用

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])

  wtform

# 安装
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

八、SqlAlchemy

  1.配置

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()

 

posted @ 2022-06-08 11:02  情调丶  阅读(51)  评论(0编辑  收藏  举报