上一章实现了登录的部分功能,之所以说是部分功能,是因为用户名和密码写成固定值肯定是不可以的,一个整体的功能,至少需要注册,登录,密码修改等,这就需要提供一个把这些值存储到数据库的能力。

当前的主流数据库分为两种,即关系数据库和NoSql数据库,对于中小型的系统来说,两种数据库性能,易用性都相当,都是很好的选择。

基础配置

这里使用SQLAlchemy数据库框架的flask集成包,即flask-SQLAlchemy来进行数据库操作。

SQLAlchemy是一个非常好的框架,简化了数据库的操作,即提供了高层次的ORM,也提供了低层次的SQL功能,使用起来非常方便。

安装方式与之前类型,还是pip命令:

pip3.6 install flask-sqlalchemy

安装完成之后,对default的配置部分进行修改,首先导入包:

from flask.ext.sqlalchemy import SQLAlchemy

然后配置链接字符串:

app.config["SQLALCHEMY_DATABASE_URI"]='mysql://root:1234@localhost/cblog'

配置请求结束后更改自动提交:

app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"]=True

实例化SQLAlchemy:

db=SQLAlchemy(app)

模型设置

安装完成之后,继续完善登录的例子,修改default.py文件,新增User模型(类)和Role模型(以示关联)

Role类

class Role(db.Model):       #需继承模型
__tablename__="roles" #db中表明,如果不设置,则会与class同的默认名
id=db.Column(db.Integer,primary_key=True) #SQLAlchemy要求必须有主键,一般命名为id即可
name=db.Column(db.String(50),unique=True) #表示name为字符串,不重复
users=db.relationship("User",backref='role') #关联user模型,并在user中添加反向引用(backref)

User类

class User(db.Model):
__tablename__="users"
id=db.Column(db.Integer,primary_key=True)
username=db.Column(db.String(50),unique=True,index=True) #此列带索引
password=db.Column(db.String(50))
role_id=db.Column(db.Integer,db.ForeignKey("roles.id")) #外键指向roles表中的id列

下面要考虑如何执行,要既方便,有不能入侵到逻辑代码,这就要求不能硬编码到逻辑代码中,比如把判断db状态的代码作为参数传递给app.run(),这时候shell就派上了用场

配置脚本

想让flask支持命令行脚本,首先需要安装flask-script扩展:

pip3.6 install flask-script

修改default.py的代码:

from flask.ext.script import Manager

mamager=Manager(app)

....

if __name__=='__main__':
#app.run(debug=True)
mamager.run()

修改过之后,再次运行:

python default.py

发现并没有成功运行,而是有提示:

可以看到,后边需要参数,分别为shell(执行脚本),runserver(启动服务)和帮助

下边启动服务:

python default.py runserver

服务成功执行

数据库更多配置

但这个时候,访问站点(127.0.0.1:5000),会出现500错误,提示没有mysql模块,这是为什么呢?很明显是没有安装mysql驱动的原因,使用pip命令安装驱动:

pip3.6 install MySQL-python

发现出现错误,显示内容为(此处仅为win系统):

根据提示,安装c++的工具包,按照提示上的下载地址

http://landinghub.visualstudio.com/visual-cpp-build-tools

下载完成直接为exe文件,安装

重启后安装MySQL-python,发现还是不可以,经百度后才发现,MySQLdb这个库最高只支持到python2.7,不在支持3.x,那只好用其他办法,使用PyMySQL库:

pip3.6 install PyMySQL

然后修改default.py的代码,增加两行:

import pymysql
pymysql.install_as_MySQLdb()

进入源码,注意这一行:

sys.modules["MySQLdb"] = sys.modules["_mysql"] = sys.modules["pymysql"]

即可成功使用并连接mysql。
浏览器输入连接,正确进入站点。

接下来,使用shell建立数据库表,进入default.py根目录:

python default.py shell
from default import db
db.create_all()

这时候如果没有报错,那么数据库表应该建立完成:

数据库迁移

那么问题来了,这时候,对模型进行修改,是不会反应到db中的,那么如果修改怎么办呢?对于当前来说,也很简单:

db.drop_all()
db.create_all()

但这个仅仅是现在调试时候使用,如果db中已经有了数据,则这个肯定是无法忍受的,这时候,就轮到数据库迁移插件Migrate登场了,首先还是一样,需要进行安装:

pip3.6 install flask-migrate

和之前一样,安装完之后修改default.py文件进行配置:

from flask.ext.migrate import Migrate,MigrateCommand

migrate=Migrate(app,db) #配置迁移
mamager.add_command("db",MigrateCommand) #配置迁移命令

然后使用init命令初始化迁移仓库

 python default.py db init

命令行显示:

然后增加migrations目录:

表示迁移文件已经初始化完成。

migrate框架提供了一些命令来进行迁移操作,分别为(使用default.py文件举例):

#根据差异创建迁移
python default.py db migrate -m "说明"
#改动差异
python default.py db upgrade
#取消差异改动
python default.py db downgrade

回到表单

接下来看看登录如何与数据库关联起来,修改login方法内的代码:

@app.route("/login",methods=["POST"])
def loginPost():
username=request.form.get("username","")
password=request.form.get("password","")
user=User.query.filter_by(username=username,password=password).first() #数据库查询
if user is not None:
session["user"]=username
return render_template("/index.html",name=username,site_name='myblog')
else:
flash("您输入的用户名或密码错误")
return render_template("/login.html") #返回的仍为登录页

执行结果非常完美。

一些总结

下面是一些关于python和db相连的总结性的东西

数据类型

db类型(SQLAlchemy) python类型
Integer int
SmallInteger int
BigInteger long
Float float
Numeric decimal.Decimal
String str
Text str
Boolean bool
Date datetime.date
Time datetime.time
DateTime datetime.datetime
PickleType python对象序列化
LargeBinary str(二进制)

列选项

primary_key True为主键(每个对象至少一列)
unique True为不允许重复
index True为创建索引
nullable True为可为空,false为不许为空
default 设置默认值
backref 为另一模型添加反向引用
primaryjoin 明确两个模型直接的链接条件
lazy 可选值:select:首次访问时加载,immediate:源对象加载后立即加载,joined使用联结立即加载,subquery:使用子查询立即加载,noload:永不加载,dynamic:不加载记录,但提供加载的查询
uselist 如果为false,则不使用列表,而使用用标量值
order_by 排序方式
secondary 多对多时指定关系表的名字
secondaryjoin 手动设置多对多关系中二级联结条件

数据库操作

db.session.add(model) 插入或修改记录(需commit)
db.session.delete(model) 删除记录(需commit)
model.query 查询记录

查询过滤器

all() 返回全部记录
filter() 将过滤器添加至原查询,返回新结果
filter_by() 将等值过滤器添加至原查询,返回新结果
limit() 限制结果数量,分页用
offset() 偏移结果,分页用
order_by() 排序
group_by() 分组
first() 返回首结果,没有则返回None
first_or_404() 返回首结果,没有则返回404响应
get() 返回主键对应的记录,没有则返回None
get_or_404() 返回主键对应的记录,没有则返回404响应
count() 返回全部数量
paginate() 返回Paginate对象,它包含指定范围内的结果  

经过这几章,登录功能已经基本完成,在下一章中将讲解用户注册的相关功能。

一个web应用的诞生(4)的更多相关文章

  1. 一个web应用的诞生(1)--初识flask

    基于flask的web应用的诞生 Flask是一个非常优秀的web框架,它最大的特点就是保持一个简单而易于扩展的小核心,其他的都有用户自己掌握,并且方便替换,甚至,你可以在社区看到众多开源的,可直接用 ...

  2. 一个web应用的诞生--使用模板

    经过了第一章的内容,已经可以做出一些简单的页面,首先用这种方式做一个登录页面,首先要创建一个login的路由方法: @app.route("/login",methods=[&qu ...

  3. 一个web应用的诞生--美化一下

    经过上一章的内容,其实就页面层来说已结可以很轻松的实现功能了,但是很明显美观上还有很大的欠缺,现在有一些很好的前端css框架,如AmazeUI,腾讯的WeUI等等,这里推荐一个和flask集成很好的b ...

  4. 一个web应用的诞生--数据存储

    上一章实现了登录的部分功能,之所以说是部分功能,是因为用户名和密码写成固定值肯定是不可以的,一个整体的功能,至少需要注册,登录,密码修改等,这就需要提供一个把这些值存储到数据库的能力. 当前的主流数据 ...

  5. 一个web应用的诞生--数据表单

    下面把角色分为两种,普通用户和管理员用户,至少对于普通用户来说,直接修改DB是不可取的,要有用户注册的功能,下面就开始进行用户注册的开发. 用户表 首先要想好用户注册的时候需要提供什么信息:用户名.密 ...

  6. 一个web应用的诞生(6)--用户账户

    之前登录注册的功能都已经完成,但是登录成功回到首页发现还是白茫茫的一片,对的,title一直都写得博客,那么最终目的也是写出一个轻博客来,但是,在发表文章之前是不是要先记录一下登录状态呢? 用户登录 ...

  7. 一个web应用的诞生(7)--结构调整

    现在所有的Py代码均写在default.py文件中,很明显这种方法下,一旦程序变的负责,那么无论对于开发和维护来说,都会带来很多问题. Flask框架并不强制要求项目使用特定的组织结构,所以这里使用的 ...

  8. 一个web应用的诞生(8)--博文发布

    这个系统一直号称轻博客,但貌似博客的功能还没有实现,这一章将简单的实现一个博客功能,首先,当然是为数据库创建一个博文表(models\post.py): from .. import db from ...

  9. 一个web应用的诞生(9)--回到用户

    在开始之前,我们首先根据之前的内容想象一个场景,用户张三在网上浏览,看到了这个轻博客,发现了感兴趣的内容,于是想要为大家分享一下心情,恩?发现需要注册,好,输入用户名,密码,邮箱,并上传头像后,就可以 ...

  10. 一个web应用的诞生(10)--关注好友

    下面回到首页中,使用一个账户登录,你肯定已经注意到了这里的内容: 没错,现在都是写死的一些固定信息,其中分享数量很容易就可以获取,只需要修改首页模板: <p class="text-m ...

随机推荐

  1. frei0r-20190715-118a589 编译 frei0r 时注意事项

    如果滤镜是 CPP 编写,需要选择 gcc Thread model: win32 模式,如果选择 posix 模式时,提示错误: 无法找到 dll 文件: frei0r-1.6.1-dlls-201 ...

  2. When specified, "proxy" in package.json must be a string.

    react项目在package.json中配置proxy之后,报错 $ npm run start > img@ start D:\xx\src\img > react-scripts s ...

  3. vtkTestHull将多个平面围成一个凸面体

    1.vtkHull produce an n-sided convex hull vtkHull is a filter which will produce an n-sided convex hu ...

  4. JS对象—数组总结(创建、属性、方法)

    JS对象—数组总结(创建.属性.方法) 1.创建字符串 1.1 new Array() var arr1 = new Array(); var arr2 = new Array(6); 数组的长度为6 ...

  5. Day05:循环问题 / 数组

    循环嵌套 循环结构中包含完整的循环结构. 注意: 循环嵌套不限层次 各种循环语句都可以互相嵌套 内层循环中出现的break和continue只作用在内层循环中 外层循环循环一次 内层循环循环一遍 Ja ...

  6. CTF—攻防练习之HTTP—PUT上传漏洞

    主机:192.168.32.152 靶机:192.168.32.159 中间件PUT漏洞 包括apache,tomcat,IIS等中间件设置支持的HTTP方法(get,post,head,delete ...

  7. 搜索框的测试checklist

    一:简单搜索输入框测试用例1:不输入任何字符,点击搜索按钮,一般搜索出网站所有的信息 2:一般搜索输入框中的有文章显示,当鼠标点击时,文章消失 3:输入全角/半角中文字符(一个字符.超长字符.已经信息 ...

  8. KVM虚拟机管理(2)

    一.virt-manager创建虚机 命令行需要下载下面的组件: CentOS7: 命令行界面升级为图形化界面 yum groupinstall "X Window System" ...

  9. ubuntu分区建议总结

    本文为转载别人的内容,结合了其他内容,进行分区的总结.其中主要是分区表格,对于ubuntu安装时,进行分区非常有用. 无论是安装Windows还是Linux操作系统,硬盘分区都是整个系统安装过程中最为 ...

  10. poj2407(欧拉函数模板题)

    题目链接:https://vjudge.net/problem/POJ-2407 题意:给出n,求0..n-1中与n互质的数的个数. 思路:欧拉函数板子题,先根据唯一分解定理求出n的所有质因数p1,p ...