《flask web开发》狗书4-6章知识点详解

第四章 Web表单

  《flask web开发》狗书前三章知识点详解
  web表单是每个网站都必须用到的,狗书里也是花了1章的篇幅来介绍,表单的内容相对第五章数据库要简单不少,不过由于模块版本的原因有部分bug,这边就针对一些知识点进行拓展。

SECRET_KEY

  开头就介绍了在app.config里插入secret_key,这边注意两点,其一是’hard to guess string’表示我们需要给这个值定一个很难猜的字符串,一般是字母数字符号都有,然后字符串长度也要相对较长;另一个就是app.config了,这是字典,在里面定义了很多的flask配置,后续可以单独定义一个Config类来封装这些配置,然后通过**app.config.from_object(Config)**把类配置到app上。

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

Flask-WTF的模块更新

  表单代码如下,其中Form类在Flask-WTF更新时已经被废除了,更新为FlaskForm,两者的内容不变;另外就是Required也变更为了DataRequired,其余的关于字段那块了解下各自的功能就行了。

class NameForm(FlaskForm):  #Form
name = StringField('What is your name?', validators=[DataRequired()]) submit = SubmitField('Submit')

‘GET’&‘POST’、session、url_for的说明

  如下是我针对index路由所写的注释,具体可以通过github上进行观看,这边要说明几点。首先对于请求方法get和post,一般我们渲染页面时,会首先通过get来获取页面信息,而当我们要提交内容时(如账号密码、上传图片),则需要通过post的请求方法,那get是不是就无法提交数据到后端呢?答案肯定是显然的,get也可以提交到后端,但最大的缺点就是提交的数据会显示到url后,细心的朋友肯定发现有的时候点进去一个链接,url的链接会变成url+?key=value的形式,这就是用get带数据请求后端的形式,key=value即是传入后端的键值对,前后端的交互是通过“字典”形式的,准确来讲json是目前的主要序列化格式。
  session在上一篇文章有描述,这边拓展一下,session是依赖于cookie实现的,而cookie和session都是字典格式,且都是纯文本格式。当前主流都采取session来保存客户端的状态信息,因为session会加密信息,而加密条件往往就是我们定义的secret_key,因此为了保证客户端加密的信息更加严谨,secret_key都会定的很难。session的实现很简单,当客户端第一次请求时,服务端就会定义session数据,这个数据是键值对形式,数据内容由你定,一般可定位user_id=xx,user_name=xx等等,然后再生成一个唯一标识符session_id,形成(session_id:加密后内容)这样的键值对保存到数据库,并把session_id返回给客户端。下次客户端访问时,比较两者的值一致即可。
  url_for是flask里使用最广泛的函数之一,因为在后端程序和模版里都可以使用,同时它是通过反解析的形式来实现定位路由的,也就是说我们有时需要变更网址,但视图函数一般是不变的,所以通过url_for(view_func)的形式,即使后续变更了网址,但服务端能照常运行。

#4章:路由定义methods,表示该路由可接收GET或POST请求,如果不定义,则默认只接收GET请求
#4章:GET和POST的区别是,前者适用于向浏览器获取数据(如页面刷新),后者适用于向浏览器发送数据(如账号密码登录)
@app.route('/', methods=['GET', 'POST'])
def index():
    #实例话NameForm类,此时每次填写即表示单独一个实例
    form = NameForm()
    #判断是否提交,如果提交了,则将提交的数据赋值到name变量,传给模版
    if form.validate_on_submit():
        #session是字典结构,get方法获取不到的话则返回None,这里第一次提交明显获取不到,所以返回None
        old_name = session.get('name')
        #判断old_name非空且不等于表单的输入数据时执行
        if old_name is not None and old_name != form.name.data:
            # flash可以把内容显示出来
            flash('Looks like you have changed your name!')
        #第一次提交时,session还无值,所以在这边给session赋值,赋值方法就是字典添加数据方法。
        #form.name.data表示:form是NameForm实例,即NameForm下的name字段的data数据,即表单输入数据
        session['name'] = form.name.data
        #依据书本内容重定向到首页
        return redirect(url_for('index'))
    #渲染模版,同时传回数据给模版,name=name第一个name表示变量name,即前端可以通过name变量获得值,
    #后一个name则表示数据,再这里就是form.name.data
    return render_template('index.html', form=form, name=session.get('name'))

  第四章相对简单,并没有其他重要的需要拓展,这边运行后结果如下:
《flask web开发》狗书4-6章知识点详解_第1张图片

第五章 数据库

  数据库的知识是web的重要部分,本章介绍了关系型数据库和非关系型数据库,但是仅针对sqlite这小型关系型数据库进行了讲解。实际上web后端更重要的非关系型数据库当属redis,是以保存键值对的形式来保存数据;而关系型数据库则是mysql尤为重要,所以本章我的实现是通过mysql来实现的。
  执行git checkout v4.0可以从github上拷贝对应的文件。

Flask- SQLAlchemy

  flask项目里大名鼎鼎的ORM就是Flask- SQLAlchemy,ORM即object-relational-Mapper,即对象关系映射,其最大的作用就是能让我们在python程序里定义数据库模型,并执行对应的数据库命令,而这个好处就是让我们能面向对象编程,而不用去理会SQL语句;另外就是可以同时应对多种关系型数据库,而我们仅需使用SQLAlchemy就行了。
  数据库配置,对于SQLAlchemy的配置,一开始我碰到也很头疼,也除了bug,但实际上理清了就会觉得很简单,一般就配置三条命令,同样的通过app.config来配置到该app身上。详细解释如下,配置sqlalchemy时,'SQLALCHEMY_DATABASE_URI’和’SQLALCHEMY_TRACK_MODIFICATIONS’是必备的,不然会报错,前者表示数据库链接,后者表示是否要追踪数据库数据的修改。

"""
5章:
basedir:获取项目的动态路径,通过os.path模块,获得当前的绝对路径,__file__返回hello.py文件名,
os.path.dirname则返回hello.py的文件夹名,通过abspath获得hello.py所在的绝对路径
配置数据库config:
'SQLALCHEMY_DATABASE_URI'指定数据库链接为sqlite
'SQLALCHEMY_TRACK_MODIFICATIONS'字面意思是追踪修改,False即表示不追踪数据库的修改记录,设置的目的是不设置会报错,是flask-sqlAlchemy强制要求设置,设置为False,因为数据库变更无须追踪;
'SQLALCHEMY_COMMIT_ON_TEARDOWN'这句命令作用很大,表示数据库如果修改数据了,会自动提交数据。
"""
basedir = os.path.abspath(os.path.dirname(__file__))
# app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]/flask_web'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

  创建Role/User数据模型时,其中对于backref和lazy的理解是一大难题,backref的作用是可以通过一个模型来关联到另一个模型,举例说明:user=User(),此时获得user实例,我们便可以通过user.role获得对应的role数据,而user.role正式backref='role’定义的。lazy则是表示可以延迟加载。

#定义Role类,一个类对应一个数据表
class Role(db.Model):
    # 表名为roles,不定义的话,SQLAlchemy会默认定义。
    __tablename__ = 'roles'
    # 依次定义id、name
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    #1对多:relationship表示链接的外键关系,第一个参数是链接外键所在的类名
    #backref==>back reference即回引,即可以通过一个表获得关系表的数据,
    # 举例:Role.users通过Role获得users的数据(下方定义),User.role(下方定义)获得role数据
    # lazy=dynamic表示动态加载,意思是当Role.users时不会立马返回结果(好处是不用立马查询数据库,利于性能优化),
    users = db.relationship('User', backref='role', lazy='dynamic')
    # 定义__repr__便于在操作数据库时可以在控制台查询对象
    def __repr__(self):
        return '' % self.name

数据表的创建

  数据库的创建,如果要用python hello.py shell执行控制台命令的话,切记第二章flask-script里的manager=Manager(app),通过把app注册到manager上,通过manager来实现控制台的命令开启功能。
  关于数据库的增删改查,要注意的就是每次修改后都要记得提交,即db.session.add()、db.session.commit(),后续会用try…except…来保证数据库的提交,一旦失败则执行db.session.rollback()进行回滚。这是利用了关系型数据库mysql的事务性,即只要整个执行语句没成功,则回滚到初始状态(未进行数据库操作状态)

数据表的查询

  数据表的查询是重中之重,web后端的工作内容就是获取前端参数,然后根据参数查询数据库的数据,最后再把数据返回给前端,由此可知查询的重要性。这边要谨记的就是先查询对象,然后再查询对象数据。比如User.query即表示查询对象,加上filter则可以限制满足条件的查询对象。最后加上all()就是表示查询全部数据,加上first()就表示查询满足条件的一条数据。以此类推,ORM的查询基本遵照该原则,另外就是可以根据数据表的一对多、多对多关系,通过定义backref和外键,得到User.role\Role.users来得到另一个关联数据表的数据。

数据表的迁移

  数据库的整个迁移问题不大,迁移完后登录mysql就可以看到定义的模型类就生成了对应的表,同时在程序文件里migration-version-py文件里面就展示了整个orm的实现,感兴趣的朋友可以了解一下。查询后在mysql如下:
《flask web开发》狗书4-6章知识点详解_第2张图片
  第五章内容讲完,执行git checkout v5.0即可拷贝文件。

第六章 电子邮件

  本章按照书里的内容很难出错,要注意以下几点:

  1. 密码是指的POP3密码,以QQ邮箱为例,进入邮箱,点击设置–>账户–>开启POP3/IMAP/SMTP的第一行,将授权码作为密码输入。
  2. 狗书里的密码账号等等通过os.environ来获取,容易出错,建议直接写在程序里就行了。
  3. templates里新增了mail文件夹,里面封装了html和txt两个文件,要记得拷贝。
      第六章内容未有什么扩展,执行git checkout v5.0即可拷贝文件。

总结

  狗书前六章是后面章节的基础,暂时说明知识点如上。

你可能感兴趣的:(flask,web)