Web开发----Flask-Bootstrap , Flask-Mail , Flask-wtf表单

自古美人都是妖i 提交于 2020-03-09 00:15:32

一、Flask中集成Bootstrap

1.Bootstrap简介
Bootstrap(http://getbootstrap.com/)是Twitter 开发的一个开源框架,它提供的用户界面组件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代Web 浏览器。
2.为什么需要在Flask中集成Bootstrap?
Flask模板集成Bootstrap。一般情况下Flask都是搭配Jinja2模板引擎来实现视图展现,
不过现在Bootstrap比较流行,内置的样式也比较好看,一些css样式和js动态都封装好了,有利于提高开发效率.
3.Flask中如何使用集成的Bootstrap?
要想在程序中集成Bootstrap,显然要对模板做所有必要的改动。
不过,更简单的方法是使用一个名为Flask-Bootstrap (相当于我们写的base.html模板)的Flask 扩展,简化集成的过程。

  • (1) Flask-Bootstrap 使用pip安装:
pip install -i https://pypi.douban.com/simple flask_bootstrap
  • (2) Flask 扩展一般都在创建程序实例时初始化,
    Flask_Bootstrap的初始化方法:
from flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)
  • (3)初始化Flask-Bootstrap 之后,就可以在程序中使用一个包含所有Bootstrap 文件的基模板base.html。
    文件位置:F:\python\Anaconda3\Lib\site-packages\flask_bootstrap\templates\bootstrap

这个模板利用Jinja2 的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中就有用来
引入Bootstrap 的元素。

  • Jinja2 中的extends 指令从Flask-Bootstrap 中导入bootstrap/base.html, 从而实现模板继承。
  • Flask-Bootstrap 中的基模板提供了一个网页框架,引入了Bootstrap 中的所有CSS 和JavaScript 文件。
  • 基模板中定义了可在衍生模板中重定义的块。block 和endblock 指令定义的块中的内容可添加到基模板中。

(4) 导航条链接
(5) 警告框链接
4.Flask-Bootstrap自定义模板块
Flask-Bootstrap 的base.html 模板还定义了很多其他块,都可在衍生模板中使用,下表列出了所有可用的块:
在这里插入图片描述
在这里插入图片描述
5.Flask-Bootstrap自定义模板块的继承实现
上表中的很多块都是Flask-Bootstrap 自用的,如果直接重定义可能会导致一些问题。例如,Bootstrap 所需的文件在styles 和scripts 块中声明。**如果程序需要向已经有内容的块中添加新内容,**必须使用Jinja2 提供的super() 函数。例如,如果要在衍生模板中添加新的JavaScript 文件,需要这么定义scripts 块:

{#链接我们自己写的css ,super() :先去执行父类base.html的css,在执行<link>的自己写的 css#}
{% block styles %}
{{ super()}}

<link rel="stylesheet" href="../static/css/main.css">
{% endblock %}

案例
继承有公共样式的html模板+实现那自己的样式
基模板为bootstrap/base.html,再定义一个继承基模板的子模板base.html,其中子模版继承基模板的样式并填充导航栏部分,再对于标题挖坑。index.html等文件继承子模板并对于标题填坑,以及基模板的content内容填坑。
run.py

from flask import Flask, render_template, flash
from flask_bootstrap import  Bootstrap


app = Flask(__name__)
app.config['SECRET_KEY'] = 'WESTOS'
bootstrap = Bootstrap(app) #初始化Bootstrap并与app关联起来
@app.route('/')
def index():
    flash('login success')
    return  render_template('index.html')

@app.route('/bbs/')
def bbs():
    return  render_template('bbs.html')


@app.route('/blog/')
def blog():
    return  render_template('blog.html')

if __name__ == '__main__':
    app.run(port=5003)

base.html
这里base.html继承了bootstrap/base.html

{% extends 'bootstrap/base.html' %}

{% block title%}

西部开源-{% block subtitle %} {% endblock %}
{% endblock %}

{#链接我们自己写的css ,super() :先去执行父类base.html的css,在执行<link>的自己写的 css#}
{% block styles %}
{{ super()}}

<link rel="stylesheet" href="../static/css/main.css">
{% endblock %}


{% block navbar %}
<nav class="navbar navbar-inverse">  <!--navbar-inverse 导航栏黑色-->
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>


{% for message in get_flashed_messages() %}

<div class="alert alert-warning alert-dismissible" role="alert">
    <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span>
    </button>
    <strong>Warning!</strong> {{ message }}
</div>

{% endfor %}


<p class="test">你好</p>

{% endblock %}

index.html
继承base.html

{%  extends 'base.html' %}

{% block subtitle %}
主页
{% endblock %}

{% block content %}
主页
{% endblock %}

bbs.html

{% extends 'base.html' %}

{% block subtitle %}
论坛
{% endblock %}
{% block content %}
<h1>bbs</h1>

{% endblock %}

blog.html

{% extends 'base.html' %}
{% block subtitle %}

博客
{% endblock %}

{% block content %}
<h1>blog</h1>

{% endblock %}

main.css

.test{
    color: green;
    font-size: 32px;
}

运行run.py
导航栏设置成功
警告组设置成功,可以点击× 关闭警告
实现标题 “西部开源-主页”

在这里插入图片描述

二、Flask 集成邮件发送

1.为什么需要使用Flask-Mail组件?
在我们开发完web系统后,一些特定的事件发生时,系统要自动发送相关邮件至管理员,运维人员和其他相关人员。
python标准库中的smtplib包也可以用在Flask程序中发送邮,但包装了smtplib的flask-mail扩展能更好地
和Flask集成。
2.如何使用flask-mail扩展发送邮件?
安装flask-mail扩展

pip install -i https://pypi.douban.com/simple flask-mail

3.项目案例:基于flask-mail 发送邮件
(1)发送邮件的时候需要设置什么?

  • 发件人账户
  • 密码
  • 收件人
  • 邮件标题
  • 邮件正文
  • QQ邮件服务器的域名或者IP

(2)配置信息设置
由于代码中发件人账户的密码不输入真正的密码而是服务器的授权码,因此QQ服务器为例来展示如何获取授权码。
可以在网上搜flask发送邮件的配置信息有哪些
发邮件需要用到qq服务器,那么qq服务器怎么设置?
在这里插入图片描述
在这里插入图片描述

(3)发送邮件准备工作
开启POP3/SMTP服务:
在这里插入图片描述
发送短信,得到授权码:tgoxgaysrbhlgeij
在这里插入图片描述
(4)详细代码

from flask_mail import Mail, Message
from flask import Flask, render_template, request, flash, redirect

app = Flask(__name__)
# 获取配置文件中的配置信息;
app.config['MAIL_SERVER']='smtp.qq.com'
app.config['MAIL_PORT']=465
app.config['MAIL_USE_SSL']=True
app.config['MAIL_USERNAME']='1104213995'
app.config['MAIL_PASSWORD']='tgoxgaysrbhlgeij'
# 初始化mail对象, 一定要先配置邮件信息;
mail = Mail(app)

# def send_mail(to, subject, filename, **kwargs):
def send_mail(to, subject, info):
    """

    :param to: 收件人
    :param subject: 邮件主题
    :param filename: 邮件正文对应的html名称
    :param kwargs: 关键字参数, 模版中需要的变量名
    :return:
    """

    msg = Message(subject=subject,
                  sender='1104213995@qq.com',
                  recipients=to,
                  )  #封装成一个对象
    msg.body = info
    msg.html='<h1>邮件正文html内容</h1>'
    # msg.html = render_template(filename + '.html',  **kwargs)
    #安全上下文,本文用的是flask发送邮件的插件,所以要关联一下flask app上下文,获取里面的变量在发送,就可以和项目结合起来。
    with app.app_context(): 
        mail.send(msg)

#当send_mail()函数绑定了html发送的内容时,这里不管有没有指定发送的info,都发送send_mail()函数中绑定的html内容。
send_mail(to=['1104213995@qq.com', '2834746621@qq.com'], subject="第2次测试",
          info="邮件测试正文") 

查看邮件:
在这里插入图片描述
4.项目案例:用户注册与邮件发送的结合
刚才是发送邮件,一般发送邮件是和后台结合起来的,使用路由和视图函数。
最常用的场景:用户在注册的时候,注册成功了,会给用户发送一条邮件。
配置信息最好独立放到一个文件config.py中
先写一个基于flask-mail发送邮件的函数,然后访问前端的注册页面,注册成功,则调用发送邮件的函数来发送邮件

run.py


from flask_mail import Mail, Message
from flask import Flask, render_template, request, flash, redirect

app = Flask(__name__)
# 获取配置文件中的配置信息;
app.config.from_pyfile('config.py')
def send_mail(to, subject, filename, **kwargs):
    """

    :param to: 收件人
    :param subject: 邮件主题
    :param filename: 邮件正文对应的html名称
    :param kwargs: 关键字参数, 模版中需要的变量名
    :return:
    """
    # 初始化mail对象, 一定要先配置邮件信息,否则没有报错但也不发送邮件;
    mail = Mail(app)
    msg = Message(subject=subject,
                  sender='1104213995@qq.com',
                  recipients=to,
                  )  #封装一个对象
    # msg.body = info
    #msg是Message()实例化出来的一个对象,里面有一个html属性,通过这个属性指定要发送的html内容(为了发送的内容格式好看)
    msg.html = render_template(filename + '.html',  **kwargs)
    #安全上下文,本文用的是flask发送邮件的插件,所以要关联一下flask app上下文,获取里面的变量在发送,就可以和项目结合起来。
    with app.app_context():
        mail.send(msg)


# send_mail(to=['976131979@qq.com', '2834746621@qq.com'], subject="第2次测试",
#           info="邮件测试正文")


@app.route('/register/', methods = ['POST', 'GET'])
def register():
    if request.method == 'GET':
        return  render_template('register.html')
    else:
        email = request.form.get('email')
        password = request.form.get('password')
        try:
            send_mail(to=[email], subject='注册通知邮件', filename='registerok', username=email)
        except Exception as e:
            #前端通过get_flashed_messages()函数获取这里flask的闪现信息
            flash("注册失败")
            return redirect('/register/')
        else:
            flash("注册成功")
            return redirect('/login/')

@app.route('/login/')
def login():
    return 'login'

if __name__ == '__main__':
    app.run(port=5004)

config.py

MAIL_SERVER = 'smtp.qq.com'
# 指定端口, 默认25, 但qq邮箱默认为 端口号465或587;
MAIL_PORT = 465

"""
由于QQ邮箱不支持非加密的协议,那么使用加密协议, 分为两种加密协议,选择其中之一即可
"""
MAIL_USE_SSL = True
MAIL_USERNAME = '1104213995'      #发件人用户
# 此处的密码并非邮箱登录密码, 而是开启pop3
MAIL_PASSWORD = "tgoxgaysrbhlgeij"
# 调试模式打开
DEBUG = True
#在使用闪现信息时,帮我们保存在session里面存储时需要加密
SECRET_KEY = 'westos'

registerok.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1 style="color: green">注册成功</h1>

尊敬的用户<strong>{{ username }}</strong>:<br/>
    您已注册网站西部开源成功, 请直接登录网站.
</body>
</html>

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#获取闪现信息#}
{% for message in get_flashed_messages() %}
<p style="color: red">{{message}}</p>
{% endfor %}

<form action="/register/" method="post">
    <input type="email" name="email" placeholder="email"><br/>
    <input type="password" name="password" placeholder="password"><br/>
    <input type="submit" value="注册">

</form>
</body>
</html>

填写注册邮箱,此邮箱如果存在则注册成功,不存在则注册失败
注册成功则返回登陆界面,并发送一条邮件给110421395@qq.com
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、Flask - wtf表单操作与用户登陆结合

1.Flask的 WTForms 扩展(Flask-WTF )
Form表单,在Web应用中无处不在。比如: 用户登录表单, 用户注册表单。

  • 所有的表单项都有共性,比如有文字输入框,单选框,密码输入框等;
  • 表单的验证也有共性,比如有非空验证,长度限制,类型验证等。

如果有个框架,能把这些共性抽象出来,那就能大量简化我们的工作。Python的 WTForms 就提供了这些功能,这里我们就要结合Flask的 WTForms 扩展, Flask-WTF ,来介绍如何在Web应用中制作表单。
Flask-wtf 安装:

pip install -i https://pypi.douban.com/simple flask-wtf

2.一个简单的表单
(1)表单文件
在这里插入图片描述
(2)常见的表单域类型
在这里插入图片描述
在这里插入图片描述
(3)常见验证规则

在这里插入图片描述
(4)视图函数文件
在这里插入图片描述

(5)验证数据
点击了表单上的提交按钮时, form.validate_on_submit() 判断会做下面两件事情:

  • 通过 is_submitted() 通过判断HTTP方法来确认是否提交了表单
  • 通过 WTForms 提供的 validate() 来验证表单数据

当validate()验证未通过时,会在表单字段下面显示我们传进去的错误提示(例如message= u’邮
箱不能为空’)。

(6)获取数据
form.data是一个字典例如:
form.data {‘email’: ‘hello@qq.com’, ‘username’: ‘hello’}
可以通过form.email.data获取email对应的value值。 可以通过form.username.data获取’hello’

验证通过后,使用 form.email.data 来获得数据,

form.email.data

WTForms 提供的静态方法.data返回一个以字段名(field name)和字段值(field value)作为键
值对的字典。

form.data['email']

(7)自定义验证

在这里插入图片描述
3.案例:Flask-wtf表单操作与用户登陆结合
(1)案例:Flask-wtf表单操作与用户登陆结合
写好登陆表单函数class LoginForm(FlaskForm):和视图函数、最终和前端页面结合起来
form.py

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, SelectField, SelectMultipleField
from wtforms.validators import DataRequired, Length, Email, EqualTo, Regexp, ValidationError


class LoginForm(FlaskForm):
    email = StringField(label="电子邮箱",
                        validators=[
                            DataRequired(message='邮箱不能为空'),
                            Length(1, 15, message="长度不符合条件"),
                            Email(message='请输入有效的邮箱地址,比如:username@domain.com')
                        ])
    password = PasswordField('密码',
                             validators=[
                                 DataRequired(message=u'密码不能为空')])
    submit = SubmitField(u'登录')

views.py

业务逻辑文件。
定义login()函数中,实例化表单对象,先返回login.html页面,填写email和password,并把form传入,验证通过后,获取email和password


from flask import  Flask, request, render_template, flash
from forms import  LoginForm, RegisterForm

app = Flask(__name__)
app.config.from_pyfile('config.py')

@app.route('/login/', methods = ['GET', 'POST'])
def login():
    # 1. 实例化表单对象
    form = LoginForm()
    # 1). 是否为post提交表单信息;
    # 2). 是否通过验证函数?
    if form.validate_on_submit():
        # 获取表单的内容
        email = form.email.data
        password = form.password.data
        if email =='westos@qq.com' and password=='westos':
            return  '登录成功'
        else:
            return  "登录失败"
    else:
        return  render_template('login.html', form=form)

if __name__ == '__main__':
    app.run(port=5005)

config.py

SECRET_KEY = 'WESTOS'

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login/" method="post">
<!--隐藏起来的标签,为了表单填写数据的安全-->
    {{ form.hidden_tag() }}
    {{form.email.label }} {{ form.email() }} {{ form.email.errors }}
    {{form.password.label }} {{ form.password() }} {{ form.password.errors }}
    {{ form.submit() }}

</form>
</body>
</html>

login.html还可以一句话实现好看的html登录页面

<!--导入Bootstrap的基模板, 自动加载css样式和js动效-->
{% extends 'bootstrap/base.html' %}
<!--导入html代码, 并起别名-->
{% import 'bootstrap/wtf.html'  as wtf %}


{%  block title %}
登录
{% endblock %}


{% block content %}
<div style="width:70%; margin: 0 auto" >

    <h1>用户登录</h1>
    <hr/>
{#    根据form对象,快速生成表单的html#}
{{ wtf.quick_form(form) }}
    </div>

{% endblock %}

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!