从零开始用 Flask 搭建一个网站(二)

news/2024/5/9 13:23:47/文章来源:https://blog.csdn.net/weixin_33843947/article/details/92057365

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

从零开始用 Flask 搭建一个网站(一) 介绍了如何搭建 Python 环境,以及 Flask 应用基本项目结构。我们要搭建的网站是管理第三方集成的控制台,类似于 Slack。 本篇主要讲解数据如何在 Flask 应用中流动,其它的框架基本上也是大同小异。

数据库

既然是数据的流动,首先要建立起存取数据的地方,也就是数据库了(这里是指关系型数据库,NoSQL 不在这讨论)。第一节中我们使用了 Flask-SQLAlchemy 管理数据库,在 Flask-SQLAlchemy 中,数据库使用 URL 指定,最流行的数据库 URL 格式如下:

|数据库引擎|URL| |:-|:-| |MySQL|mysql://username:password@hostname/database| |Postgres|postgresql://username:password@hostname/database| |SQLite(Unix)|sqlite:absolute/path/to/database| |SQLite(Windows)|sqlite:///c:/absolute/path/to/database|

在 config.py 中我们已经指定了数据库 URL,如果使用云平台部署程序,直接将生成的数据库 URL 写到 config.py 中 SQLALCHEMY_DATABASE_URI 即可。这里我们使用的是 SQLite 数据库。Flask-SQLAlchemy 采用数据库抽象层来操作数据库,也称为对象关系映射(Object-Relational Mapper, ORM),在用户不知不觉的情况下把高层的面向对象操作转换成低层的数据库指令,因此易用性好。我们已经在 app/__init__.py 中实例化了 SQLAlchemy 类:

app/__init__.py

from flask_sqlalchemy import SQLAlchemy
...
db = SQLAlchemy()
...
定义模型

模型类可以理解为数据库中的一张表,Flask-SQLAlchemy 提供了一个基类和一系列辅助类和函数来让我们定义模型的结构。我们直接在 app 文件夹下创建一个 models.py 文件。鉴于每个网站需求都不一样,所存的数据也不同,但本质上是大同小异的。这里以笔者网站需求为例,需要创建 Developer,Integration 和 Channel 三个表。

app/models.py 部分代码

from flask import current_app
from app import dbclass Developer(db.Model):    __tablename__ = 'developers'    id = db.Column(db.Integer, primary_key=True)    dev_key = db.Column(db.String(40), unique=True, index=True)    platform = db.Column(db.String(50))    platform_id = db.Column(db.String(40), unique=True)    username = db.Column(db.String(150), index=True)    integrations = db.relationship('Integration', backref='developer')    channels = db.relationship('Channel', backref='developer')class Integration(db.Model):    __tablename__ = 'integrations'    id = db.Column(db.Integer, primary_key=True)    integration_id = db.Column(db.String(40), unique=True)    name = db.Column(db.String(100))    description = db.Column(db.String(150))    icon = db.Column(db.String(150))    channel = db.Column(db.String(150))    token = db.Column(db.String(150))    developer_id = db.Column(db.Integer, db.ForeignKey('developers.id'))class Channel(db.Model):    __tablename__ = 'channels'    id = db.Column(db.Integer, primary_key=True)    developer_id = db.Column(db.Integer, db.ForeignKey('developers.id'))    channel = db.Column(db.String(150))    def __repr__(self):        return '<Channel %r>' % self.channel

上面的每个 Class 都继承了 Model 类,因此每个类在数据库中都体现为一张表,表名用 __tablename__ 表示,一般用复数形式。这里主要讲一下一对多的关系。可以看到上面 Developer 和 Integration 及 Channel 都有一个一对多的关系,一个用户可以有多个集成及多个频道。 看到这两句:

integrations = db.relationship('Integration', backref='developer')
developer_id = db.Column(db.Integer, db.ForeignKey('developers.id'))

第一句表明添加到 Developer 表的 integrations 属性表示这个关系的面向对象视角,对于一个 Developer 实例,integrations 属性将返回与 Developer 相关的所有 Integration,db.relationship() 第一个参数表明关系的另一端是哪个模型,backref 参数向 Integration 添加一个 developer 属性,从而定义反向关系。第二句是在 Integration 表中创建一个 developer_id 字段,这个字段被定义为外键,就是这个外键建立起了关系。传给 db.ForeignKey() 的参数 'developers.id' 表明这列的值是 developers 表中行的 id 值。另外,__repr__() 方法返回一个具有可读性的字符串表示模型,可以在调试和测试时使用。下面我们就在命令行中操作一下数据库。 首先执行:

//创建 migrations 文件夹及相关文件
python manage.py db init

然后执行 :

//自动创建迁移脚本
python manage.py db migrate
//创建数据表或者升级到最新版本
python manage.py db upgrade

以后模型类有改动,比如删除或添加列,都要执行这两个命令,更新数据库表。现在在项目目录下应该自动生成了名为 dev 的数据库。 接下来执行如下命令进入 Python Shell:

python manage.py shell
创建表

使用 db.create_all() 就可以根据模型类创建表。如图:

使用 db.drop_all() 方法就可以删除所有的表,但是这种方式比较粗暴,所有的数据也一同销毁了。

插入行

以下命令在数据库表中插入了一条数据:

通过数据库会话 db.session 来管理对数据库所做的改动,在准备把对象写入数据库之前,首先要添加到会话中,然后用 commit() 方法提交会话。接下来我们继续插入一条 Integration 数据:

>>>from app.models import Integration,Channel
>>>integration = Integration(integration_id='i0001',name='github',description='first >>>application',channel='github_event',developer=developer)
>>> db.session.add(integration)
>>> db.session.commit()

注意上面的 developer 属性,正是我们在 models.py 中 Developer 模型中定义的一对多关系 integrations 属性的 backref 值, 所谓的反向关系即指在 Integration 表中每条数据都有一个 developer 属性指向 Developer 表中的某条数据,这是一对多关系的高级表示。现在可以用 developer.integrations 来查看该 developer 拥有的哪些集成,运行截图如下:

修改行

在提交数据库会话之前,改变对象的某个属性然后再提交即可更新行数据。如:

>>> developer.username = 'lisi'
>>> db.session.add(developer)
>>> db.session.commit()

运行截图:

删除行

调用 db.session.delete() 方法即可删除行:

>>>db.session.delete(developer)
>>>db.session.commit()
查询行

Flask-SQLAlchemy 为每个模型提供了 query 对象,最基本的查询是返回表中的所有记录:

>>>Developer.query.all()

使用过滤器可以进行更精确的查询:

>>>Developer.query.filter_by(platform='qq').all()

如果你退出了 shell 会话,前面创建的对象就不会以 Python 对象的形式存在,而是作为各自数据库表中的行。这时需要重数据库中读取行,再重新创建 Python 对象,如:

>>> new_developer = Developer.query.filter_by(dev_key=12345).first()

注意上面的 first() 方法,如果不加上,将返回一个 BaseQuery 对象,这样就不能直接用 new_developer 来访问它的属性值。

在视图函数中操作数据库

上面介绍的所有数据库操作可以直接在视图函数中进行。假设我们要做一个简陋的注册功能,下面我们就来看看如何从网页中获取数据并保存在数据库中。我们先定义一个用户模型:

app/models.py

class User(db.model):__tablename__ = 'users'id = db.column(db.Integer, primary_key=True)username = db.column(db.String(50), unique=True)password = db.column(db.String(100))def __repr__(self):return '<User %r>'  % self.username

然后在 main 文件夹下创建一个 forms.py 文件。

app/main/forms.py

from flask_wtf import Form
from wtforms import StringField, SubmitField, PasswordField
from wtforms.validators import DataRequiredclass UserForm(Form):      username = StringField('Input your username', validators=[DataRequired()])    password = PasswordField('Input your password', validators=[DataRequired()])    submit = SubmitField('Submit')

我们使用了 flask-wtf 扩展(pip install flask-wtf)来处理表单。 然后我们用在 index 页面中显示这个表单。

index.html

{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}{% block title %}注册{% endblock %}{% block content %}{% for message in get_flashed_messages() %}    <div class="alert alert-warning">        <button type="button" class="close" data-dismiss="alert">×</button>        {{ message }}    </div>{% endfor %}<div id="form"><div class="col-md-4">{{ wtf.quick_form(form) }}</div></div>
{% endblock %}

现在回到 views.py 中,在我们的视图函数中作如下改动:

app/main/views.py

...
from .forms import UserForm
from ..models import User
from app import db@main.route('/', methods=['GET', 'POST'])
def signin():form = UserForm()if form is None:flash('Should input username and password')elif  form.validate_on_submit():user = User(username=form.username.data, password=form.password.data)db.session.add(user)try:db.session.commit()flash('User created !')except:db.session.rollback()flash('User create failed')return render_template('index.html', form=form)

接下来我们运行一下这个小试验:

python manage.py runserver

总结

本节我们介绍了在 Flask 中是如何使用 Flask-SQLAlchemy 、Flask-Migrate来管理数据库,并且示范了数据从网页储存到数据库的过程,这只是最基础的部分,下一节我们将探索如何在网页上发送请求并且得到数据,以及如何在页面之间传递数据。

作者:KenChoi - 极光

原文:从零开始用 Flask 搭建一个网站(二)

知乎专栏:极光日报

转载于:https://my.oschina.net/jpushtech/blog/877364

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_767192.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android中文网站

Google Developers中国网站发布 用户评价&#xff1a; / 55 差好 最后更新于 2016年12月09日 点击数&#xff1a;15209 我们很高兴地宣布&#xff0c;Google Developers 中国网站 (developers.google.cn) 正式发布&#xff01; Google Developers 中国网站是特别为中国开发者…

python获取网站http://www.weather.com.cn 城市 8-15天天气

参考一个前辈的代码&#xff0c;修改了一个案例开始学习beautifulsoup做爬虫获取天气信息&#xff0c;前辈获取的是7日内天气&#xff0c; 我看旁边还有8-15日就模仿修改了下。其实其他都没有变化&#xff0c;只变换了获取标签的部分。但是我碰到 一个span获取的问题&#xff0…

网站静态化处理—前后端分离—上(6)

前文讲到了CSI技术&#xff0c;这就说明网站静态化技术的讲述已经推进到了浏览器端了即真正到了web前端的范畴了&#xff0c;而时下web前端技术的前沿之一就是前后端分离技术了&#xff0c;那么在这里网站静态化技术和前后端分离技术产生了交集&#xff0c;所以今天我将讨论下前…

交友网站数据库曝光了150万用户信息

据外媒报道&#xff0c; 近日一个新西兰交友网站对一个包含150多万用户信息的数据库进行了安全性保护。这家网站的运营商C&Z Tech Limited表示&#xff0c; MacKeeper安全研究中心的安全专家在发现这个问题后向该公司发出提醒。 C&Z 在发给MacKeeper的邮件中表示&#…

基于SSM的校园招聘网站

​源码编号&#xff1a;D-E22 项目类型&#xff1a;也属于Java web项目/Java EE项目&#xff08;非开源&#xff09; 项目名称&#xff1a;基于SSM的校园招聘网站 [Recruit] 当前版本&#xff1a;V1.0.1版本 难度等级&#xff1a;✩✩ 复杂程度&#xff1a;✩✩✩ 点击查看…

基于Java web的旅游网站(源码+文档)

源码编号&#xff1a;B-E57点击查看&#xff08;分类规则&#xff09; 项目类型&#xff1a;Java web项目/Java EE项目&#xff08;非开源&#xff09; 项目名称&#xff1a;基于java web的旅游网站 [travel] 当前版本&#xff1a;V1.0.0版本 用户类型&#xff1a;双角色&…

基于JSP的旅游网站系统

源码编号&#xff1a;B-E74点击查看&#xff08;分类规则&#xff09; 项目类型&#xff1a;Java web项目/Java EE项目&#xff08;非开源&#xff09; 项目名称&#xff1a;基于JSPServlet的旅游景点服务平台&#xff08;旅游网站&#xff09; 源码作者&#xff1a;霹雳、逍…

基于JSP+Servlet的宠物养护网站

源码编号&#xff1a;B-E77 项目名称&#xff1a;基于JSPServlet的宠物养护网站 源码作者&#xff1a;逍遥游制作 论文作者&#xff1a;逍遥游撰写 当前版本&#xff1a;V1.0版本 用户类型&#xff1a;三角色&#xff08;用户、管理员&#xff09; 项目架构&#xff1a;B…

有图有真相 好图好流量 十个妙招优化网站图片

【51CTO.com快译】对于任何一个电子商务网站来说&#xff0c;图片优化都是必不可少的环节。图片对于消费者和网友的影响妙不可言&#xff0c;优化图片是一门网店里的艺术。图片的清晰度、吸引力和加载时间都将直接影响到你的用户。下面我们就为大家介绍一些优化图片的小技巧&am…

自学Java网站推荐

自学Java可以学会吗&#xff1f; 很多同学问我自学Java能学会吗&#xff0c;我可以很负责任的告诉你完全可以&#xff01;因为俺当初就是自学Java找到的工作&#xff0c;目前互联网资源丰富&#xff0c;只要你想学肯定能学会&#xff01;&#xff01;&#xff01; 自学Java最…

大型网站技术基石之 OpenStack

我们知道虚拟化能够充分的利用资源&#xff0c;带来各种各样的好处。 当一个网站不大&#xff0c;只需要四五台机器就可以支撑的时候&#xff0c;可以采用手工的方式虚拟机&#xff0c;但是当网站流量很高&#xff0c;需要成千上万台机器的时候&#xff0c;那就非常不方便了。 …

云服务器 ECS 搭建WordPress网站:安装 WordPress

安装 WordPress请先下载最新版的 WordPress&#xff0c;网址&#xff1a; https://cn.wordpress.org/ 。也可直接到阿里云市场选择WordPress镜像完成一键部署&#xff0c;点击查看。 操作步骤 1.将下载的安装包解压缩。 2.打开 Xshell&#xff0c;然后打开 Xftp&#xff0c;将解…

云服务器 ECS 建站教程:部署 LAMP (CentOS 7.2)

部署 LAMP &#xff08;CentOS 7.2&#xff09;简介 LAMP指LinuxApacheMysql/MariaDBPerl/PHP/Python是一组常用来搭建动态网站或者服务器的开源软件&#xff0c;本身都是各自独立的程序&#xff0c;但是因为常被放在一起使用&#xff0c;拥有了越来越高的兼容度&#xff0c;共…

​详解SEO优化中所使用的新浪博客站群

SEO优化的过程中网站的权重是关键词排名不可或缺的因素&#xff0c;为了提升网站的权重SEOer通常会利用第三方平台的高权重为SEO所用&#xff0c;今天给大家讲一个关于新浪博客站群的概念以及具体的操作方法。顾名思义新浪博客站群分解开来通俗点来说就是新浪博客的集群&#x…

什么样的自学Java网站才适合学习者?

前言 有很多Java学习者常常问我一些在学习Java过程中遇到的问题&#xff0c;我发现很多问题总是卡在该知识点的概念层面&#xff0c;比如&#xff1a;一个多线程的程序这样加锁对不对&#xff1f;什么是原子性&#xff1f; 这个Lambda表达式为什么编译不通过&#xff1f;这个问…

web设计中那些因素可能影响网站后期优化

开发十年&#xff0c;就只剩下这套Java开发体系了 >>> web设计中那些因素可能影响网站后期优化。 1.网站代码的简洁实用性。网站源文件html代码、js代码、css代码等应尽可能的压缩处理。能用jquery-min.js的最好不要用jquery.js&#xff1b;css里能合在一起的样式尽…

静态网站内容区

1.em与strong&#xff0c;b与i的区别 1.b、i属于修饰标签&#xff1b;strong、em属于内容类标签&#xff1b; 2.b、strong标签表现为加粗样式&#xff1b;em、i表现为倾斜样式&#xff1b; 3.strong、em表强调&#xff1b;strong比em语气更强烈&#xff1b; 4.strong和em真正做…

通过TMG防火墙后网站的GZIP压缩就失效了?

前段时间和一些做网站开发测试的朋友在聊天时&#xff0c;他们提到在做网站测试时发现只要是在公司内走微软TMG访问一些带有GZIP格式的页面时&#xff0c;发现GZIP就失效了&#xff0c;我正好一直在搞ISA/TMG&#xff0c;就想让我帮想想看是哪里出问题了&#xff1f;当时聊时我…

ajax网站拖拽效果

转自&#xff1a;http://hi.baidu.com/yan5201314/blog/item/b69e543d01550bee3c6d9743.html 2006年11月18日 星期六 上午 00:23近日在Syosyumes Blog上的看到GOOGLE的个性化主页拖搁功能的实现方法可以借鉴&#xff0c;他的方法是用Jscript实现&#xff0c;不包含记忆功能&…

.Net Core建站(3):搭建三层架构

啊&#xff0c;终于到写三层架构的时候了&#xff0c;老实说&#xff0c;我都不知道自己这个算不算三层架构&#xff0c;姑且就当它是吧&#xff0c;具体属于哪一个体系&#xff0c;希望有大佬指点一下(^o^)&#xff0f; 不晓得有人注意到没有&#xff0c;我写了三篇博客&#…