• Flask学习之旅--数据库


    一、写在前面

      在Web开发中,数据库操作是很重要的一部分,因为网站的很多重要信息都保存在数据库之中。而Flask在默认情况下是没有数据库、表单验证等功能的,但是可以用Flask-extension为Web应用添加这些功能。

    二、Flask SQLite

      SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统。由于Python对SQlite有内置的支持,因此在Flask应用程序中和SQLite进行交互是比较容易的。

      首先需要创建一个SQLite数据库“user.db”,并在其中创建一张用户表。代码如下:

    1 import sqlite3
    2 
    3 
    4 conn = sqlite3.connect("user.db")
    5 print("Connected!")
    6 
    7 conn.execute("CREATE TABLE USER(username TEXT, password TEXT, EMAIL TEXT)")
    8 print("Table created successfully!")
    9 conn.close()

      这里就不贴HTML代码了,就是一个注册页面,在注册的时候会将用户输入的用户名、密码和邮箱传到后台。在app.py中需要导入sqlite3模块,然后连接前面创建的user.db,在建立连接之后创建一个游标对象,然后编写SQL语句进行数据库操作,整个过程都算是比较容易的。app.py中的代码如下:

     1 from flask import Flask, render_template, request
     2 import sqlite3 as sql
     3 
     4 app = Flask(__name__)
     5 
     6 
     7 @app.route('/register', methods=['GET', 'POST'])
     8 def register():
     9     if request.method == 'GET':
    10         return render_template('register.html')
    11     else:
    12         msg = ""
    13         try:
    14             username = request.form["usr"]
    15             password = request.form["pwd"]
    16             email = request.form["email"]
    17             print(username, password, email)
    18             with sql.connect("user.db") as con:
    19                 cur = con.cursor()
    20                 cur.execute("INSERT INTO USER (username, password, email) VALUES (?,?,?)",
    21                             (username, password, email))
    22                 con.commit()
    23             msg = "注册成功!"
    24         except:
    25             con.rollback()
    26             msg = "注册失败!请重试!"
    27         finally:
    28             con.close()
    29             return render_template('register.html', msg=msg)
    30 
    31 
    32 if __name__ == '__main__':
    33     app.run()

    三、Flask SQLAlchemy

      Flask-SQLAlchemy是Flask扩展,它将对SQLAlchemy的支持添加到Flask应用程序中。在Flask Web应用程序中使用原始SQL对数据库执行CRUD操作可能很繁琐,不过SQLAlchemy 为应用程序开发人员提供了SQL的全部功能和灵活性。它是一个对数据库的抽象,让开发者不用这些编写SQL语句,而是使用其提供的接口去操作数据库,这其中涉及到一个非常重要的思想:ORM(Object Relation Mapping,对象关系映射),主要的功能是实现模型对象到关系型数据库数据的映射。说白了就是使用通过对象去操作数据库。

    1.Flask-SQLAlchemy安装

      使用pip install flask-sqlalchemy进行安装。不过在安装的时候可能会出现如下错误:

    pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.

      这是因为在下载python库的时候,由于国内网络原因,导致python包的下载速度非常慢,查看pip 文档,只要在 pip的时候控制超时即可, 具体参数为 --default-timeout=100, 后面的时间可以自己指定。因此可以用如下命令进行下载安装:

    pip install --default-timeout=100 flask-sqlalchemy

    2.Flask-SQLAlchemy配置

      从此模块导入SQLAlchemy类,创建一个Flask应用程序对象并为要使用的数据库设置URI的代码如下:

    from flask_sqlalchemy import SQLAlchemy


    app = Flask(__name__)

    # URI的格式为:用户名:密码@ip地址:端口号(默认可以不写)/数据库名
    app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:qwer1234@localhost/flask"

    3.配置的时候可能出现的问题及解决办法

    1)ModuleNotFoundError: No module named 'MySQLdb'

    解决办法:

      使用pymysql模块,URI改为:

    app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:qwer1234@localhost/flask"

    2)Warning: (1366, "Incorrect string value: '\xD6\xD0\xB9\xFA\xB1\xEA...' for column 'VARIABLE_VALUE' at row 481")

    解决办法:

      改用mysql-connector,使用pip install mysql-connector下载安装,URI改为:

    app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqlconnector://root:qwer1234@localhost/flask"

    3)sqlalchemy.exc.NotSupportedError: (mysql.connector.errors.NotSupportedError) Authentication plugin 'caching_sha2_password' is not supported

    解决办法:

      出现这个错误是因为MySQL8.0采用了Use Strong Password Encryption for Authentication即强密码加密,而mysql.connector的引擎不支持caching_sha2_password的加密格式,所以解决思路有如下几种:

      (1)重装MySQL,在Authentication Method中选择第二项(重装比较麻烦,我就没有尝试):

      (2)在client端,将加密格式选择成mysql_native_password,命令如下(个人尝试后无效):

    ALTER user 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root'

      (3)最后一种是我自己摸索出来的,就是在URI设置的时候加上一个参数auth_plugin并设置为mysql_native_password:

    app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqlconnector://root:qwer1234@localhost/flask?auth_plugin=mysql_native_password"

    4.Flask-SQLAlchemy的基本操作

    1) 常用查询过滤器:

      过滤器得到的还只是一些对象,需要使用执行器来获取真正的数据。

    filter(): 把过滤器添加到原查询上,返回一个新查询,需要使用模型类名去获取字段来进行比较;

    filter_by():把等值(只能使用=比较操作)过滤器添加到查询上,返回一个新查询;

    order_by():根据指定条件对查询结果进行排序,返回一个新查询;

    group_by():根据指定条件对原查询结果进行分组,返回一个新查询。

    2.)常用查询执行器

    all():以列表的形式返回查询的所有结果;

    first():返回查询的第一个结果;

    first_or_404():同first(), 只不过如果没有找到的话,返回404错误;

    get():返回指定主键对应的行;

    get_or_404():返回指定主键对应的行,如不存在,返回404错误;

    count():返回查询结果的数量;

    paginate():返回一个Paginate对象,包含指定范围内的结果。

    3.)查询条件

    startswith('xx'):查询以xx开头的所有数据;

    endswith('xx'):查询以xx结尾的所有数据;

    not_():取反;

    and_():返回and()条件满足的所有数据;

    or_():返回or()条件满足的所有数据。

    5.使用示例

      app.py中代码如下:

     1 from flask_sqlalchemy import SQLAlchemy
     2 import mysql.connector
     3 
     4 
     5 app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqlconnector://root:qwer1234@localhost/flask?auth_plugin=mysql_native_password"
     6 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
     7 app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
     8 
     9 
    10 # 获取SQLAlchemy实例对象
    11 db = SQLAlchemy(app)

      然后新建一个model.py,编写如下代码进行测试:

     1 from app import db
     2 
     3 
     4 # 创建模型对象
     5 class User(db.Model):
     6     __tablename__ = "users"
     7     id = db.Column(db.Integer, primary_key=True)
     8     username = db.Column(db.String(16), unique=True)
     9     password = db.Column(db.String(16))
    10     email = db.Column(db.String(32), unique=True)
    11 
    12     def __repr__(self):
    13         return '<User %r>' % self.username
    14 
    15 
    16 # 1.创建表
    17 db.create_all()
    18 print("Created Successfully!")
    19 
    20 # 2.增加记录
    21 usr1 = User()
    22 usr1.id = 1
    23 usr1.username = "wang"
    24 usr1.password = "wangwang"
    25 usr1.email = "wang@163.com"
    26 usr2 = User(id=2, username="yang", password="yang", email="yang@163.com")
    27 db.session.add(usr1)
    28 print("Add usr1")
    29 db.session.add(usr2)
    30 print("Add usr2")
    31 db.session.commit()
    32 
    33 # 3.查询记录,注意查询返回对象,如果查询不到返回None
    34 users1 = User.query.all()  # 查询所有
    35 print(users1)
    36 print("User Count:", len(users1))
    37 
    38 # 4.删除
    39 user = User.query.get(1)
    40 db.session.delete(user)
    41 print("Delete usr1")
    42 db.session.commit()
    43 
    44 users2 = User.query.all()  # 查询所有
    45 print(users2)
    46 print("User Count:", len(users2))

      运行结果如下所示:

    Created Successfully!
    Add usr1
    Add usr2
    [<User 'wang'>, <User 'yang'>]
    User Count: 2
    Delete usr1
    [<User 'yang'>]
    User Count: 1

  • 相关阅读:
    我对NHibernate的感受(3):有些尴尬的集合支持
    NHibernate3.0剖析:Query篇之NHibernate.Linq标准查询
    NHibernate3.0剖析:Query篇之NHibernate.Linq增强查询
    30个优秀的后台管理界面设计案例分享
    NHibernate Session Flush的作用
    NHibernate 3 Extending the Linq Provider to fix some System.NotSupportedException
    Activity初步
    公司间交易学习笔记概述
    公司间交易学习笔记值映射
    BOM配置
  • 原文地址:https://www.cnblogs.com/TM0831/p/11081576.html
Copyright © 2020-2023  润新知