2020年5月

在Flask中处理请求时,应用会生成一个“请求上下文”对象。整个请求的处理过程,都会在这个上下文对象中进行。这保证了请求的处理过程不被干扰。
Flask中,类似于request的对象,其实是绑定到了一个werkzeug.local.Local对象上。这样,即使是同一个对象,那么在多个线程中都是隔离的。

应用上下文和请求上下文

应用上下文和请求上下文都是存放到一个LocalStack的栈中。和应用app相关的操作就必须要用到应用上下文,比如通过current_app获取当前的这个app。和请求相关的操作就必须用到请求上下文,比如使用url_for反转视图函数。

  1. 在视图函数中,不用担心上下文的问题。因为视图函数要执行,那么肯定是通过访问url的方式执行的,那么这种情况下,Flask底层就已经自动的帮我们把请求上下文和应用上下文都推入到了相应的栈中。
  2. 如果想要在视图函数外面执行相关的操作,比如获取当前的app(current_app),或者是反转url,那么就必须要手动推入相关的上下文:

    • 手动推入app上下文:

      # 第一种方式:
      app_context = app.app_context()
      app_context.push()
      # 第二种方式:
      with app.app_context():
          print(current_app)
    • 手动推入请求上下文:推入请求上下文到栈中,会首先判断有没有应用上下文,如果没有那么就会先推入应用上下文到栈中,然后再推入请求上下文到栈中:

      with app.test_request_context():
          print(url_for('my_list'))

注意: 为什么上下文需要放在栈中:

  1. 应用上下文:Flask底层是基于werkzeug,werkzeug是可以包含多个app的,所以这时候用一个栈来保存。如果你在使用app1,那么app1应该是要在栈的顶部,如果用完了app1,那么app1应该从栈中删除。方便其他代码使用下面的app。
  2. 如果在写测试代码,或者离线脚本的时候,我们有时候可能需要创建多个请求上下文,这时候就需要存放到一个栈中了。使用哪个请求上下文的时候,就把对应的请求上下文放到栈的顶部,用完了就要把这个请求上下文从栈中移除掉。

保存全局对象的g对象:

g对象是在整个Flask应用运行期间都是可以使用的。并且他也是跟request一样,是线程隔离的。这个对象是专门用来存储开发者自己定义的一些数据,方便在整个Flask程序中都可以使用。一般使用就是,将一些经常会用到的数据绑定到上面,以后就直接从g上面取就可以了,而不需要通过传参的形式,这样更加方便。

在Flask中钩子函数是使用特定的装饰器装饰的函数。那么这种函数就叫做钩子函数。

  1. before_first_request:Flask项目第一次部署后会执行的钩子函数。
  2. before_request:请求已经到达了Flask,但是还没有进入到具体的视图函数之前调用。一般这个就是在视图函数之前,我们可以把一些后面需要用到的数据先处理好,方便视图函数使用。
  3. context_processor:使用这个钩子函数,必须返回一个字典。这个字典中的值在所有模版中都可以使用。这个钩子函数的函数是,如果一些在很多模版中都要用到的变量,那么就可以使用这个钩子函数来返回,而不用在每个视图函数中的render_template中去写,这样可以让代码更加简洁和好维护。
  4. errorhandler:在发生一些异常的时候,比如404错误,比如500错误。那么如果想要优雅的处理这些错误,就可以使用errorhandler来出来。需要注意几点:

    • 在errorhandler装饰的钩子函数下,记得要返回相应的状态码。
    • 在errorhandler装饰的钩子函数中,必须要写一个参数,来接收错误的信息,如果没有参数,就会直接报错。
    • 使用flask.abort可以手动的抛出相应的错误,比如开发者在发现参数不正确的时候可以自己手动的抛出一个400错误。

小编今天再给表加字段的时候,发现数据库报错,总是不能加入数据显示(Errcode: 28 - No space left on device), Time: 0.102000s这么一个错误。空间已满,这种情况一般是由于某个程序的日志较多造成的。
我们执行df -lh。查看写磁盘情况,发现/dev/vda1 40G 38G 0 100% /
达到了100%。
我们再执行du -sh /* .就可以发现哪个文件夹内容较多了。然后我们就可以一级一级的执行该方法,知道找到最终的日志文件就可以了。然后清理下我们不需要的日志文佳,数据库就正常了。

舒尔特方格也叫舒尔特表格,也叫苏尔特方格、苏尔特表格。
是世界上最专业最普及最简略的训练法,普遍利用于飞翔员航天员的训练,也是学生提高注意力的有效训练法,此法保持一段时光就会觉得很显明的提高。舒尔特方格用于注意力训练,适合各个年龄段。标准的为5X5表格,数完25个数字所用时间越短,注意力水平越高。注意力水平与学习成绩密切相关。5-7岁年龄组达到30秒以下为优秀,7-12岁年龄组能达到20秒以下为优秀,学习成绩应名列前茅。成年人也可以练习,平均水平为20秒,最快可以达到4秒以下。练习应当循序渐进,不要着急。

方法:
舒尔特方格是在一张方形卡片上画上1CM × 1CM 的25 个方格(注意:方格必定是要这个尺寸的),格子内任意填写上阿拉伯数字1 ― 25 的共25 个数字。做成程序员的小编这里把他做成了小程序,大家只要用微信,扫一下下面的二维码就可以直接练习了。并且数字也是随机的。
舒尔特方格

训练时,请求被测者用手指按1 ― 25 的次序依次指出其地位,同时诵读出声。舒尔特方格不仅可用来测量儿童注意力的稳固性,而且用这套图表保持天天练习一遍,那么孩子注意力水平就能得到大幅度提高。
从1开端,边念边指出相应的数字,直到25为止。同时诵读出声,施测者一旁记载所用时光。数完25 个数字所用光阴越短,注意力水平越高。以12 ―― 14 岁年龄组为例,能到达16 "以上为优良,学习成就应是名列前茅,26 "属于中等水平,班级排名会在中游或偏下,36 "则问题较大,测验会呈现不合格现象。18 岁及以上成年人最好可到达8 "的程度,20 "为中等程度。

同时小编也为大家设置了不通难度的等级从3X3到9X9。

flask实现文件的上传与访问

  1. 在前台的模版中,form表单里面需要指定encotype='multipart/form-data'。然后通过<input type="file" name="photo" />来选择文件。
  2. 后台获取上传的文件,可以使用request.files.get('photo')来获取。
  3. 保存文件之前,先要使用werkzeug.utils.secure_filename来对上传上来的文件名进行一个过滤。这样才能保证不会有安全问题。
  4. 获取到上传上来的文件后,使用photo.save(路径)方法来保存文件。、
  5. 从服务器上读取文件,应该定义一个url与视图函数,来获取指定的文件。在这个视图函数中,使用send_from_directory(文件的目录,文件名)来获取。
  6. 可以通过send_from_directory(UPLOAD_PATH,filename),来访问上穿的文件,第一个参数为路径,第二个参数为文件名。
    示例代码如下:

    UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')
    
    
    @app.route('/upload/',methods=['GET','POST'])
    def upload():
     # 获取描述信息
     photo = request.files.get("photo")
     filename = secure_filename(photo.filename)
     photo.save(os.path.join(UPLOAD_PATH,filename))
     print(desc)
     return '文件上传成功'
    
    @app.route('/images/<filename>/')
    def get_image(filename):
     return send_from_directory(UPLOAD_PATH,filename)

    注意:对上传文件使用表单验证:

  7. 定义表单的时候,对文件的字段,需要采用FileField这个类型。
  8. 验证器应该从flask_wtf.file中导入。flask_wtf.file.FileRequired是用来验证文件上传是否为空。flask_wtf.file.FileAllowed用来验证上传的文件的后缀名。
  9. 在视图文件中,使用from werkzeug.datastructures import CombinedMultiDict来把request.formrequest.files来进行合并。再传给表单来验证。
    示例代码如下:

    from werkzeug.datastructures import CombinedMultiDict
    form = UploadForm(CombinedMultiDict([request.form,request.files]))

flask中的WTForms的主要作用就是做表单验证,把用户提交上来的数据进行验证是否合法,也就类似于表单验证,还可以做模版渲染。

使用方法

做表单验证:

  1. 自定义一个表单类,继承自wtforms.Form类。
  2. 定义好需要验证的字段,字段的名字必须和模版中那些需要验证的input标签的name属性值保持一致
  3. 在需要验证的字段上,需要指定好具体的数据类型。
  4. 在相关的字段上,通过validators指定验证器,验证器的格式是一个列表。
  5. 以后在视图中,就只需要使用这个表单类的对象,并且把需要验证的数据,也就是request.form传给这个表单类,以后调用form.validate()方法,如果返回True,那么代表用户输入的数据都是合法的,否则代表用户输入的数据是有问题的。如果验证失败了,那么可以通过form.errors来获取具体的错误信息。
    示例代码如下:
    ReistForm类的代码:

    class RegistForm(Form):
     username = StringField(validators=[Length(min=3,max=10,message='用户名长度必须在3到10位之间')])
     password = StringField(validators=[Length(min=6,max=10)])
     password_repeat = StringField(validators=[Length(min=6,max=10),EqualTo("password")])

    视图函数中的代码:

    form = RegistForm(request.form)
    if form.validate():
     return "success"
    else:
     print(form.errors)
     return "fail"

常用的过滤器

  1. Email:验证上传的数据是否为邮箱。
  2. EqualTo:验证上传的数据是否和另外一个字段相等,常用的就是密码和确认密码两个字段是否相等。
  3. InputRequir:原始数据的需要验证。如果不是特殊情况,应该使用InputRequired
  4. Length:长度限制,有min和max两个值进行限制。
  5. NumberRange:数字的区间,有min和max两个值限制,如果处在这两个数字之间则满足。
  6. Regexp:自定义正则表达式进行验证。
  7. URL:验证是否是URL格式。
  8. UUID:验证是否是UUID格式。

注意:在验证器里面我们可以通过message来指定错误的返回内容。

自定义验证器

  1. 首先定义一个方法,方法的名字规则是:validate_字段名(self,filed)
  2. 在方法中,使用field.data可以获取到这个字段的具体的值。
  3. 如果数据满足条件,那么可以什么都不做。如果验证失败,那么应该抛出一个wtforms.validators.ValidationError的异常,并且把验证失败的信息传到这个异常类中。
    示例代码:

    captcha = StringField(validators=[Length(4,4)])
     def validate_captcha(self,field):
         if field.data != 'sunxiaoning':
             raise ValidationError('验证码错误!')

Flask-SQLAlchemy是针对flask开发而封装的一个包,这里面使得SQLAlchemy操作更方便,基本用法和SQLAlchemy类似。

安装:

pip install flask-sqlalchemy

数据库连接:

  1. 跟sqlalchemy一样,定义好数据库连接字符串DB_URI。
  2. 将这个定义好的数据库连接字符串DB_URI,通过SQLALCHEMY_DATABASE_URI这个键放到app.config中。示例代码:app.config["SQLALCHEMY_DATABASE_URI"] = DB_URI.
  3. 使用flask_sqlalchemy.SQLAlchemy这个类定义一个对象,并将app传入进去。示例代码:db = SQLAlchemy(app)

示例代码:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

HOSTNAME = '' # 主机地址
PORT = '3306' # 端口号
DATABASE = '' # 数据库
USERNAME = '' # 数据库账号
PASSWORD = '' # 数据库密码

# dialect+driver://username:password@host:port/database
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8mb4".format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE)

app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

创建ORM模型:

  1. 还是跟使用sqlalchemy一样,定义模型。现在不再是需要使用delarative_base来创建一个基类。而是使用db.Model来作为基类。
  2. 在模型类中,ColumnStringInteger以及relationship等,都不需要导入了,直接使用db下面相应的属性名就可以了。
  3. 在定义模型的时候,可以不写__tablename__,那么flask_sqlalchemy会默认使用当前的模型的名字转换成小写来作为表的名字,并且如果这个模型的名字使用了多个单词并且使用了驼峰命名法,那么会在多个单词之间使用下划线来进行连接。虽然flask_sqlalchemy给我们提供了这个特性,但是不推荐使用。

将ORM模型映射到数据库:

  1. 删除数据库:db.drop_all()
  2. 创建数据库:db.create_all()

使用session:

以后session也不需要使用sessionmaker来创建了。直接使用db.session就可以了。操作这个session的时候就跟之前的sqlalchemysession是一样的。

外键

在从表中增加一个字段,指定这个字段外键的是哪个表的哪个字段。注意:从表中外键的字段,必须和父表的主键字段类型保持一致。
示例代码如下:

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False)

class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer,primary_key=True,autoincrement=True)
    title = Column(String(50),nullable=False)
    content = Column(Text,nullable=False)
    # 外键
    uid = Column(Integer,ForeignKey("user.id"))

外键约束有以下几项:

  1. RESTRICT:父表数据被删除,会阻止删除。默认就是这一项。
  2. NO ACTION:在MySQL中,同RESTRICT。
  3. CASCADE:级联删除。
  4. SET NULL:父表数据被删除,子表数据会设置为NULL。

ORM关系以及一对多

SQLAlchemy提供了一个relationship,这个类可以定义属性,以后在访问相关联的表的时候就直接可以通过属性访问的方式就可以访问。
示例代码:

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False)

    # articles = relationship("Article")

    def __repr__(self):
        return "<User(username:%s)>" % self.username

class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer,primary_key=True,autoincrement=True)
    title = Column(String(50),nullable=False)
    uid = Column(Integer,ForeignKey("user.id"))

    author = relationship("User",backref="articles")

另外,可以通过backref来指定反向访问的属性名称。articles是有多个。他们之间的关系是一个一对多的关系。

一对一的关系

在sqlalchemy中,如果想要将两个模型映射成一对一的关系,那么应该在父模型中,指定引用的时候,要传递一个uselist=False这个参数进去。就是告诉父模型,以后引用这个从模型的时候,不再是一个列表了,而是一个对象了。
示例代码:

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False)

    extend = relationship("UserExtend",uselist=False)

    def __repr__(self):
        return "<User(username:%s)>" % self.username

class UserExtend(Base):
    __tablename__ = 'user_extend'
    id = Column(Integer, primary_key=True, autoincrement=True)
    school = Column(String(50))
    uid = Column(Integer,ForeignKey("user.id"))

    user = relationship("User",backref="extend")

当然,也可以借助sqlalchemy.orm.backref来简化代码:

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False)

    # extend = relationship("UserExtend",uselist=False)

    def __repr__(self):
        return "<User(username:%s)>" % self.username

class UserExtend(Base):
    __tablename__ = 'user_extend'
    id = Column(Integer, primary_key=True, autoincrement=True)
    school = Column(String(50))
    uid = Column(Integer,ForeignKey("user.id"))

    user = relationship("User",backref=backref("extend",uselist=False))

多对多的关系

  1. 多对多的关系需要通过一张中间表来绑定他们之间的关系。
  2. 先把两个需要做多对多的模型定义出来
  3. 使用Table定义一个中间表,中间表一般就是包含两个模型的外键字段就可以了,并且让他们两个来作为一个“复合主键”。
  4. 在两个需要做多对多的模型中随便选择一个模型,定义一个relationship属性,来绑定三者之间的关系,在使用relationship的时候,需要传入一个secondary=中间表。

ORM层面的删除数据

ORM层面删除数据,会无视mysql级别的外键约束。直接会将对应的数据删除,然后将从表中的那个外键设置为NULL。如果想要避免这种行为,应该将从表中的外键的nullable=False
在SQLAlchemy,只要将一个数据添加到session中,和他相关联的数据都可以一起存入到数据库中了。这些是怎么设置的呢?其实是通过relationship的时候,有一个关键字参数cascade可以设置这些属性:

  1. save-update:默认选项。在添加一条数据的时候,会把其他和他相关联的数据都添加到数据库中。这种行为就是save-update属性影响的。
  2. delete:表示当删除某一个模型中的数据的时候,是否也删掉使用relationship和他关联的数据。
  3. delete-orphan:表示当对一个ORM对象解除了父表中的关联对象的时候,自己便会被删除掉。当然如果父表中的数据被删除,自己也会被删除。这个选项只能用在一对多上,不能用在多对多以及多对一上。并且还需要在子模型中的relationship中,增加一个single_parent=True的参数。
  4. merge:默认选项。当在使用session.merge,合并一个对象的时候,会将使用了relationship相关联的对象也进行merge操作。
  5. expunge:移除操作的时候,会将相关联的对象也进行移除。这个操作只是从session中移除,并不会真正的从数据库中删除。
  6. all:是对save-update, merge, refresh-expire, expunge, delete几种的缩写。

懒加载

在一对多,或者多对多的时候,如果想要获取多的这一部分的数据的时候,往往能通过一个属性就可以全部获取了。比如有一个作者,想要或者这个作者的所有文章,那么可以通过user.articles就可以获取所有的。但有时候我们不想获取所有的数据,比如只想获取这个作者今天发表的文章,那么这时候我们可以给relationship传递一个lazy='dynamic',以后通过user.articles获取到的就不是一个列表,而是一个AppenderQuery对象了。这样就可以对这个对象再进行一层过滤和排序等操作。
通过lazy='dynamic',获取出来的多的那一部分的数据,就是一个AppenderQuery对象了。这种对象既可以添加新数据,也可以跟Query一样,可以再进行一层过滤。
总而言之一句话:如果你在获取数据的时候,想要对多的那一边的数据再进行一层过滤,那么这时候就可以考虑使用lazy='dynamic'
lazy可用的选项:

  1. select:这个是默认选项。还是拿user.articles的例子来讲。如果你没有访问user.articles这个属性,那么sqlalchemy就不会从数据库中查找文章。一旦你访问了这个属性,那么sqlalchemy就会立马从数据库中查找所有的文章,并把查找出来的数据组装成一个列表返回。这也是懒加载。
  2. dynamic:这个就是我们刚刚讲的。就是在访问user.articles的时候返回回来的不是一个列表,而是AppenderQuery对象。

subquery

子查询可以让多个查询变成一个查询,只要查找一次数据库,性能相对来讲更加高效一点。不用写多个sql语句就可以实现一些复杂的查询。那么在sqlalchemy中,要实现一个子查询,应该使用以下几个步骤:

  1. 将子查询按照传统的方式写好查询代码,然后在query对象后面执行subquery方法,将这个查询变成一个子查询。
  2. 在子查询中,将以后需要用到的字段通过label方法,取个别名。
  3. 在父查询中,如果想要使用子查询的字段,那么可以通过子查询的返回值上的c属性拿到。
    整体的示例代码如下:

    stmt = session.query(User.city.label("city"),User.age.label("age")).filter(User.username=='sunxiaoning').subquery()
    result = session.query(User).filter(User.city==stmt.c.city,User.age==stmt.c.age).all()

Query

查询内容

  1. 模型对象。指定查找这个模型中所有的对象。
  2. 模型中的属性。可以指定只查找某个模型的其中几个属性。

    user = session.query(User).first()
    username = session.query(User.username).first()

常用的filter操作符

  1. equals:

    user = session.query(User).filter(User.name == "sunxiaoning").first()
  2. not equals:

    query.filter(User.username != 'sunxiaoning').all()
  3. like:

    query.filter(User.username.like('%ning%'))
  4. in:

    query.filter(User.username.in_(['sun','xiao','ning']))
    
    query.filter(User.username.in_(
        session.query(User.username).filter(User.username.like('%sun%'))
    ))
  5. not in:

    query.filter(~User.username.in_(['sun','xiao','ning']))
  6. is null:

    query.filter(User.username==None)
    # OR
    query.filter(User.username.is_(None))
  7. is not null:

    query.filter(User.username != None)
    # OR
    query.filter(User.username.isnot(None))
  8. and:

    from sqlalchemy import and_
    query.filter(and_(User.username=='sun', User.age<18))
    # 或者是传递多个参数
    query.filter(User.username=='sun', User.age<18)
    # 或者是通过多次filter操作
    query.filter(User.username=='sun').filter(User.age<18)
  9. or:

    from sqlalchemy import or_  
    query.filter(or_(User.username=='sun', User.age<18))
  10. MATCH:

    query.filter(User.username.match('sun'))
SQLAlchemy中filter()和filter_by()的区别:
1、filter引用列名时,使用“类名.属性名”的方式,比较使用两个等号“==”
2、filter_by引用列名时,使用“属性名”,比较使用一个等号“=”
3、在使用多条件匹配的时候,filter需要借助sqlalchemy里的and_ ; 而filter_by不需要,直接把多个匹配条件写在一起
4、在使用多条件匹配时,用到>=、>、<=、<的情况,貌似不能使用filter_by。可能是姿势不对

返回列表(List)和单项(Scalar)

  • all()返回一个列表。
  • first()返回至多一个结果,而且以单项形式,而不是只有一个元素的tuple形式返回这个结果。
  • one()返回且仅返回一个查询结果。当结果的数量不足一个或者多于一个时会报错。一般使用first()。
  • one_or_none():从名称可以看出,当结果数量为0时返回None, 多于1个时报错。
  • scalar()和one()类似,但是返回单项而不是tuple。

排序:

  1. order_by:可以指定根据这个表中的某个字段进行排序,如果在前面加了一个-,代表的是降序排序。
  2. 在模型定义的时候指定默认排序:有些时候,不想每次在查询的时候都指定排序的方式,可以在定义模型的时候就指定排序的方式。有以下两种方式:

    • relationship的order_by参数:在指定relationship的时候,传递order_by参数来指定排序的字段。
    • 在模型定义中,添加以下代码:

      __mapper_args__ = {
       "order_by": _id
       }
  3. 正序排序与倒序排序:默认是使用正序排序。如果需要使用倒序排序,那么可以使用这个字段的desc()方法,或者是在排序的时候使用这个字段的字符串名字,然后在前面加一个负号。

计数

Query定义了一个很方便的计数函数count()

limit、offset和切片操作:

  1. limit:可以限制每次查询的时候只查询几条数据。
  2. offset:可以限制查找数据的时候过滤掉前面多少条。
  3. 切片:可以对Query对象使用切片操作,来获取想要的数据。可以使用slice(start,stop)方法来做切片操作。也可以使用[start:stop]的方式来进行切片操作。一般在实际开发中,中括号的形式是用得比较多的。希望大家一定要掌握。示例代码如下:

    users = session.query(User).order_by(User._id.desc())[0:10]

    聚合函数

    • func.count:统计行的数量。
    • func.avg:求平均值。
    • func.max:求最大值。
    • func.min:求最小值。
    • func.sum:求和。
      func上,其实没有任何聚合函数。但是因为他底层做了一些魔术,只要mysql中有的聚合函数,都可以通过func调用。

      session.query(func.count(User.id)).all()

    group_by 和 having:

    根据某个字段进行分组。比如想要根据性别进行分组,来统计每个分组分别有多少人,那么可以使用以下代码来完成:

    session.query(User.username,func.count(User.id)).group_by(User.username).all()

    having是对查找结果进一步过滤。比如只想要看未成年人的数量,那么可以首先对年龄进行分组统计人数,然后再对分组进行having过滤。示例代码如下:

    result = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age >= 18).all()

我们在使用SQLAlchemy做数据的增删改查操作,我们是通过session对象来实现的。

  1. 构建session对象:所有和数据库的ORM操作都必须通过一个叫做session的会话对象来实现,通过以下代码来获取会话对象:

    from sqlalchemy.orm import sessionmaker
    
    engine = create_engine(DB_URI)
    session = sessionmaker(engine)()
  2. 添加对象:

    class User(Base):
        __tablename__ = 'user'
    
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50))
        age = Column(Integer)
    • 创建对象,也即创建一条数据:

      u = User(name='xiaoning',age=18,country='china')
    • 将这个对象添加到session会话对象中:

      session.add(u)
    • 将session中的对象做commit操作(提交):

      session.commit()
    • 一次性添加多条数据:

      u1 = User(name='xiaoning',age=19,country='china')
      u2 = User(name='boke',age=20,country='china')
      session.add_all([u1,u2])
      session.commit()
  3. 查找对象:

    # 查找某个模型对应的那个表中所有的数据:
    all_user = session.query(User).all()
    # 使用filter_by来做条件查询
    all_user = session.query(User).filter_by(name='xiaoning').all()
    # 使用filter来做条件查询
    all_user = session.query(User).filter(User.name=='xiaoning').all()
    # 使用get方法查找数据,get方法是根据id来查找的,只会返回一条数据或者None
    user = session.query(User).get(primary_key)
    # 使用first方法获取结果集中的第一条数据
    user = session.query(User).first()

    小编在下一篇文章中将详细讲解查询。

    SQLAlchemy中filter()和filter_by()的区别
    1、filter引用列名时,使用“类名.属性名”的方式,比较使用两个等号“==”
    2、filter_by引用列名时,使用“属性名”,比较使用一个等号“=”
    3、在使用多条件匹配的时候,filter需要借助sqlalchemy里的and_ ; 而filter_by不需要,直接把多个匹配条件写在一起
    4、在使用多条件匹配时,用到>=、>、<=、<的情况,貌似不能使用filter_by。可能是姿势不对
  4. 修改对象:首先从数据库中查找对象,然后将这条数据修改为你想要的数据,最后做commit操作就可以修改数据了。

    user = session.query(User).first()
    user.name = 'boke'
    session.commit()
  5. 删除对象:将需要删除的数据从数据库中查找出来,然后使用session.delete方法将这条数据从session中删除,最后做commit操作就可以了。

    user = session.query(User).first()
    session.delete(user)
    session.commit()