python框架之Flask基础篇(二)-------- 数据库的操作

栏目: Python · 发布时间: 6年前

内容简介:python框架之Flask基础篇(二)-------- 数据库的操作

1.flask连接数据库的四步:

  1. 倒入第三方数据库扩展包:from flask_sqlalchemy import SQLAlchemy
  2. 配置config属性,连接数据库:

    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask"

    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

  3. 创建数据库first_flask
  4. 创建操作数据库对象:db = SQLAlchemy(app)

下面直接上代码解释:

# -*- coding:utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# url的格式为:数据库的协议://用户名:密码@ip地址:端口号(默认可以不写)/数据库名
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@localhost/first_flask"
# 动态追踪数据库的修改. 性能不好. 且未来版本中会移除. 目前只是为了解决控制台的提示才写的
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# 创建数据库的操作对象
db = SQLAlchemy(app)


class Role(db.Model):

    __tablename__ = "roles"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(16),unique=True)
    # 给Role类创建一个uses属性,关联users表。
    # backref是反向的给User类创建一个role属性,关联roles表。这是flask特殊的属性。
    users = db.relationship('User',backref="role")
    # 相当于__str__方法。
    def __repr__(self):
        return "Role: %s %s" % (self.id,self.name)


class User(db.Model):
    # 给表重新定义一个名称,默认名称是类名的小写,比如该类默认的表名是user。
    __tablename__ = "users"
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(16),unique=True)
    email = db.Column(db.String(32),unique=True)
    password = db.Column(db.String(16))
    # 创建一个外键,和django不一样。flask需要指定具体的字段创建外键,不能根据类名创建外键
    role_id = db.Column(db.Integer,db.ForeignKey("roles.id"))

    def __repr__(self):
        return "User: %s %s %s %s" % (self.id,self.name,self.password,self.role_id)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 删除所有的表
    db.drop_all()
    # 创建表
    db.create_all()

    ro1 = Role(name = "admin")
    # 先将ro1对象添加到会话中,可以回滚。
    db.session.add(ro1)
    
    ro2 = Role()
    ro2.name = 'user'
    db.session.add(ro2)
    # 最后插入完数据一定要提交
    db.session.commit()

    us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=ro2.id)
    us3 = User(name='chen', email='chen@126.com', password='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=ro1.id)
    us5 = User(name='tang', email='tang@itheima.com', password='158104', role_id=ro2.id)
    us6 = User(name='wu', email='wu@gmail.com', password='5623514', role_id=ro2.id)
    us7 = User(name='qian', email='qian@gmail.com', password='1543567', role_id=ro1.id)
    us8 = User(name='liu', email='liu@itheima.com', password='867322', role_id=ro1.id)
    us9 = User(name='li', email='li@163.com', password='4526342', role_id=ro2.id)
    us10 = User(name='sun', email='sun@163.com', password='235523', role_id=ro2.id)
    db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
    db.session.commit()
    app.run(debug=True)

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面插播一条bug:

当把表格创建完成,注释这两句话:

 # 删除所有的表
    db.drop_all()
    # 创建表
    db.create_all()

然后向表格里面插入数据,此时会出现这样的错误:

sqlalchemy.exc.IntegrityError: (_mysql_exceptions.IntegrityError) (1062, "Duplicate entry 'admin' for key 'name'") [SQL: u'INSERT INTO roles (name) VALUES (%s)'] [parameters: ('admin',)]

查了网上的好多资料说把字段的约束unique=True去掉就好了,但是根本原因不在这。

原因就是因为app.run(debug=True)。开启debug模式之后,当我们修改代码的时候,比如将删除表和创建表这两句话注释,然后打开插入数据的注释。这个过程debug模式默认就已经把程序运行一遍了。此时数据库就已经有了数据,当我们再次手动执行的时候,又往数据库中插入了一条数据,这时候就会报错。因为字段的约束是唯一性的unique,所以解决的办法有两种:

第一种:就是不要将删除表和创建表这两句话注释,每次执行都要带着这两个句话。无论是debug模式自动执行还是我们手动执行程序,都会先删除表然后再创建表,所以执行多少次都不怕。

第二种:关闭debug模式。就是这样app.run()

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2.数据库的增删改查:

1.以下的方法都是返回一个新的查询,需要配合执行器使用。

filter(): 过滤,功能比较强大。
filter_by():过滤,用在一些比较简单的过滤场景。

order_by():排序。默认是升序,降序需要导包: from sqlalchemy import * 。 然后引入desc方法。比如order_by(desc("email")).按照邮箱字母的降序排序。

group_by():分组。

2.以下都是一些常用的执行器:配合上面的过滤器使用。

get():获得id等于几的函数。比如:查询id=1的对象。get(1)。切记:括号里没有“id=”,直接传入id的数值就ok。因为该函数的功能就是查询主键等于几的对象。

all():查询所有的数据。

first():查询第一个数据。

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

paginate():分页查询,返回一个分页对象。paginate(参数1,参数2,参数3)

参数1:当前是第几页,参数2:每页显示几条记录,参数3:是否要返回错误。

返回的分页对象有三个属性:items:获得查询的结果,pages:获得一共有多少页,page:获得当前页。

3.常用的逻辑符:

需要倒入包才能用的有:from sqlalchemy import * 

not_ and_ or_  还有上面说的排序desc。

常用的内置的有:in_      表示某个字段在什么范围之中。

4.其他关系的一些数据库查询:

endswith():以什么结尾。

startswith():以什么开头。

contains():包含

5.下面体会一下上面的这些用法:

1. 查询所有用户数据
User.query.all()
2. 查询有多少个用户
User.query.count()
3. 查询第1个用户
User.query.first()

4. 查询id为4的用户[3种方式]
User.query.get(4)
User.query.filter_by(id=4).first()    
User.query.filter(User.id==4).first()

filter:(类名.属性名==)
filter_by:(属性名=)

filter_by: 用于查询简单的列名,不支持比较运算符
filter比filter_by的功能更强大,支持比较运算符,支持or_、in_等语法。


5. 查询名字结尾字符为g的所有数据[开始/包含]
User.query.filter(User.name.endswith('g')).all()
User.query.filter(User.name.contains('g')).all()

6. 查询名字不等于wang的所有数据[2种方式]
 from sqlalchemy import not_
注意了啊:逻辑查询的格式:逻辑符_(类属性其他的一些判断)
User.query.filter(not_(User.name=='wang')).all()

User.query.filter(User.name!='wang').all()


7. 查询名字和邮箱都以 li 开头的所有数据[2种方式]
from sqlalchemy import and_
User.query.filter(and_(User.name.startswith('li'), User.email.startswith('li'))).all()

User.query.filter(User.name.startswith('li'), User.email.startswith('li')).all()



8. 查询password是 `123456` 或者 `email` 以 `itheima.com` 结尾的所有数据
from sqlalchemy import or_
User.query.filter(or_(User.password=='123456', User.email.endswith('itheima.com'))).all()


9. 查询id为 [1, 3, 5, 7, 9] 的用户列表
User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all()


10. 查询name为liu的角色数据
关系引用
User.query.filter_by(name='liu').first().role.name

11. 查询所有用户数据,并以邮箱排序
排序
User.query.order_by('email').all()  默认升序
User.query.order_by(desc('email')).all() 降序
12. 查询第2页的数据, 每页只显示3条数据
help(User.query.paginate)
三个参数: 1. 当前要查询的页数 2. 每页的数量 3. 是否要返回错误

pages = User.query.paginate(2, 3, False)
pages.items # 获取查询的结果
pages.pages # 总页数
pages.page # 当前页数

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Bulletproof Web Design

Bulletproof Web Design

Dan Cederholm / New Riders Press / 28 July, 2005 / $39.99

No matter how visually appealing or packed with content a Web site is, it isn't succeeding if it's not reaching the widest possible audience. Designers who get this guide can be assured their Web site......一起来看看 《Bulletproof Web Design》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具