Flak扩展库的使用

表单

一、原生表单

  • 准备模板文件login.html

    <form method="post" action="/check/">
        用户名:<input name="username" /><br />
        <input type="submit" />
    </form>
    
  • 添加视图函数,并渲染模板文件:

    @app.route('/login/')
    def login():
        return render_template('login.html')
    
  • 添加检验视图函数:

    @app.route('/check/', methods=['POST'])
    def check():
        return '登录成功'
    
  • 一个路由接收两种请求:

    @app.route('/login/', methods=['GET', 'POST'])
    def login():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            # request.form存放了所有的POST请求数据
            # return request.form.get('username')
            # request.values存放了所有GET/POST请求数据
            return request.values.get('username')
    

二、flask-wtf

  • 说明:表单处理的扩展库,提供了CSRF、字段校验等功能,使用非常方便

  • 安装:pip install flask-wtf

  • 使用:

    • 创建注册表单类
    from flask_wtf import FlaskForm #导入表单基类
    from wtforms import StringField,PasswordField,SubmitField
    from wtforms.validators import DataRequired,Length,EqualTo,Email
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'SECRET_KEY'
    maanger = Manager(app)
    
    #自定义表单注册类
    class Register(FlaskForm):
        #username为当前标签的name值 用户名为到那个前标签展示的左侧的label标签 点击用户名 出发当前标签选中节点
        username = StringField('用户名',validators=[DataRequired('请输入用户名'),Length(min=6,max=12,message='用户名长度范围在6~12位之间')])
        userpass = PasswordField('密码',validators=[DataRequired('请输入密码'),Length(min=6,max=12,message='密码长度范围在6~12位之间')])
        confirm = PasswordField('确认密码',validators=[DataRequired('请输入确认密码'),EqualTo('userpass',message='密码和确认密码不一致')])
        email = StringField('邮箱',validators=[DataRequired('请输入邮箱地址'),Email(message='请输入正确的邮箱')])
        submit = SubmitField('注册')
    
    • 添加视图函数,创建表单对象,并渲染模板文件:
    #注册
    @app.route('/register/',methods=['GET','POST'])
    def register():
        form = Register() #实例化表单类
        #这个方法是实现表单校验功能的 csrf,数据正确性 都通过了 则为真 否则为假
        if form.validate_on_submit():
            # print(request.form)
            print(form.username) #拿到username的整个标签
            print(form.username.data) #取出username里面的value值
            return '数据提交过来了'
        return render_template('register.html',form=form)
    
    • 原生渲染表单
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h2>flask-wtf的表单类</h2>
    <form action="{{ url_for('register') }}" method="post">
        {# csrf #}
        {{ form.csrf_token }}
        {{ form.username.label }}
        {{ form.username(style="color:red;",class='myself',placeholder='请输入用户名...') }} #给当前的标签添加属性和值 关键字参数
        #循环迭代取出验证失败的错误信息(也就是你在验证器里的属性message的值)
        {% for error in form.username.errors %}
            <span style="color:red;">{{ error }}</span>
        {% endfor %}
        <br>
        {{ form.userpass.label }}
        {{ form.userpass }}
        {% for error in form.userpass.errors %}
            <span style="color:red;">{{ error }}</span>
        {% endfor %}
        <br>
        {{ form.confirm.label }}
        {{ form.confirm() }}
        {% for error in form.confirm.errors %}
            <span style="color:red;">{{ error }}</span>
        {% endfor %}
        <br>
        {{ form.email.label }}
        {{ form.email() }}
        {% for error in form.email.errors %}
            <span style="color:red;">{{ error }}</span>
        {% endfor %}
        <br>
        {{ form.submit() }}
    </form>
    </body>
    </html>
    
    • 宏定义表单
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {# 定义表单宏 #}
    {% macro filed(att) %}
        <tr>
            <td>{{ att.label() }}</td>
            <td>{{ att() }}</td>
            {% for error in att.errors %}
            <td style="color:red;">{{ error }}</td>
            {% endfor %}
        </tr>
    {% endmacro %}
    <form action="" method="post">
    <table>
        {{ filed(form.username) }}
        {{ filed(form.userpass) }}
        {{ filed(form.confirm) }}
        {{ filed(form.email) }}
        <tr>
            <td>{{ form.submit() }}</td>
        </tr>
    </table>
    </form>
    </body>
    </html>
    
    • 使用bootstrap方式进行快速渲染
    {% extends 'common/base.html' %}
    {% block title %}
        注册
    {% endblock %}
    {% from 'bootstrap/wtf.html' import quick_form %}
    {% block pagecontent %}
        <div class="row">
            <div class="col-md-8">.col-md-8</div>
            <div class="col-md-4">{{ quick_form(form) }}</div>
        </div>
    {% endblock %}
    
  • 常见字段类型

    字段类型说明
    StringField普通文本字段
    Submit提交按钮
    PasswordField密文字段
    HiddenField隐藏字段
    RadioField单选框
    BooleanField复选框
    FileField文件上传
    SelectField下拉框
    TextAreaField文本域
    IntegerField文本字段,值为整数
    FloatField文本字段,值为浮点数
    DateFielddatetime.date类型
    DateTimeFielddatetime.datetime类型
  • 常见验证器

    验证器说明
    Length规定字符长度
    DataRequired确保字段有值(提示信息与所写的不一致)
    Email邮箱地址
    IPAddressIP地址
    NumberRange数值的范围
    URL统一资源定位符
    EqualTo验证两个字段的一致性
    Regexp正则验证
    • 自定义验证函数
    from wtforms.validators import ValidationError
    
    class NameForm(FlaskForm):
    	。。。
        def validate_name(self, field):
            if len(field.data) < 6:
                raise ValidationError('用户名不能少于6个字符')
    

    总结:写字段验证函数,就是写一个’validate_字段名’的函数

三、flask-moment

  • 说明:专门负责时间本地化显示的扩展库,使用非常方便

  • 安装:pip install flask-moment

  • 使用:

    • python代码
    from flask_moment import Moment
    
    moment = Moment(app)
    
    @app.route('/mom/')
    def mom():
        from datetime import datetime, timedelta
        current_time = datetime.utcnow() + timedelta(seconds=-60)
        return render_template('mom.html', current_time=current_time)
    
    • 模板文件
    {# 加载jQuery #}
    {{ moment.include_jquery() }}
    
    {# 加载moment.js #}
    {{ moment.include_moment() }}
    
    {# 设置语言 #}
    {{ moment.locale('zh-CN') }}
    
    {# 简单的格式化时间显示 #}
    <div>时间:{{ moment(current_time).format('LLLL') }}</div>
    <div>时间:{{ moment(current_time).format('LLL') }}</div>
    <div>时间:{{ moment(current_time).format('LL') }}</div>
    <div>时间:{{ moment(current_time).format('L') }}</div>
    
    {# 自定义格式化显示 #}
    <div>自定义:{{ moment(current_time).format('YYYY-MM-DD HH:mm:ss') }}</div>
    
    {# 显示时间差 #}
    <div>发表于:{{ moment(current_time).fromNow() }}</div>
    

四、文件上传

原生实现
  • 模板文件

    <form method="post" enctype="multipart/form-data">
        <input type="file" name="photo" /><br />
        <input type="submit" value="上传" />
    </form>
    
  • 视图函数

    import os
    
    # 配置上传文件保存目录
    app.config['UPLOADED_FOLDER'] = os.path.join(os.getcwd(), 'static/upload')
    
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        if request.method == 'POST':
            # 获取上传对象
            photo = request.files.get('photo')
            if photo:
                # 拼接保存路径名
                pathname = os.path.join(app.config['UPLOADED_FOLDER'], photo.filename)
                # 保存上传文件
                photo.save(pathname)
                return '上传成功'
            else:
                return '上传失败'
        return render_template('upload.html')
    
  • 上传限制设置

    # 允许上传的文件后缀
    ALLOWED_SUFFIX = set(['png', 'jpg', 'jpeg', 'gif'])
    
    # 判断是否是允许的后缀
    def allowed_file(filename):
        return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_SUFFIX
        
    # 限制请求大小
    app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024 * 8
    
    # 展示上传的图片
    @app.route('/uploaded/<filename>')
    def uploaded(filename):
        return send_from_directory(app.config['UPLOADED_FOLDER'], filename)
      
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        img_url = None
    
        if request.method == 'POST':
            # 获取上传对象
            photo = request.files.get('photo')
            if photo and allowed_file(photo.filename):
                # 拼接保存路径名
                pathname = os.path.join(app.config['UPLOADED_FOLDER'], photo.filename)
                # 保存上传文件
                photo.save(pathname)
                # 构造上传文件的url
                img_url = url_for('uploaded', filename=photo.filename)
        return render_template('upload.html', img_url=img_url)
    
flask-uploads
  • 说明:极大的的简化了文件上传相关的操作,使用非常方面。

  • 安装:pip install flask-uploads

  • 使用:

    • 配置
    from flask_uploads import UploadSet, IMAGES
    from flask_uploads import configure_uploads
    from flask_uploads import patch_request_class
    import os
    
    app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()
    app.config['MAX_CONTENT_LENGTH'] = 8 * 1024 * 1024
    # 创建上传对象
    photos = UploadSet('photos', IMAGES)
    # 配置上传对象
    configure_uploads(app, photos)
    # 配置上传文件大小,默认为64M,
    # 若设置为None,则以MAX_CONTENT_LENGTH配置为准
    patch_request_class(app, size=None)
    
    • 视图函数
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        img_url = None
        if request.method == 'POST':
            # 获取上传对象
            photo = request.files.get('photo')
            if photo:
                # 保存上传文件,返回文件名
                filename = photos.save(photo)
                # 根据文件名获取上传文件的URL
                img_url = photos.url(filename)
        return render_template('upload.html', img_url=img_url)
    
综合使用
  • 要求:结合flask-bootstrap、flask-wtf、flask-uploads等完成文件上传

  • 使用:

    • 配置
    from flask_wtf import FlaskForm
    from flask_wtf.file import FileField, FileAllowed, FileRequired
    from wtforms import SubmitField
    from flask_uploads import UploadSet, IMAGES
    from flask_uploads import configure_uploads
    from flask_uploads import patch_request_class
    from flask_bootstrap import Bootstrap
    import os
    
    bootstrap = Bootstrap(app)
    
    app.config['SECRET_KEY'] = '123456'
    app.config['MAX_CONTENT_LENGTH'] = 8 * 1024 * 1024
    app.config['UPLOADED_PHOTOS_DEST'] = os.path.join(os.getcwd(), 'static/upload')
    
    photos = UploadSet('photos', IMAGES)
    configure_uploads(app, photos)
    patch_request_class(app, size=None)
    
    class UploadForm(FlaskForm):
        photo = FileField('头像', validators=[FileRequired(message='请选择文件'), 
                                            FileAllowed(photos, message='只能上传图片文件')])
        submit = SubmitField('上传')
    
    • 视图函数
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        img_url = None
        form = UploadForm()
        if form.validate_on_submit():
            photo = form.photo.data
            filename = photos.save(photo)
            img_url = photos.url(filename)
        return render_template('upload.html', form=form, img_url=img_url)
    
    • 模板文件
    {% extends 'bootstrap/base.html' %}
    
    {% from 'bootstrap/wtf.html' import quick_form %}
    
    {% block title %}完整的文件上传{% endblock %}
    
    {% block content %}
        <div class="container">
            {% if img_url %}
                <img src="{{ img_url }}">
            {% endif %}
            {{ quick_form(form) }}
        </div>
    {% endblock %}
    
    • 生成随机文件名
    def random_string(length=32):
        import random
        base_str = 'abcdefghijklmnopqrstuvwxyz1234567890'
        return ''.join(random.choice(base_str) for i in range(length))
      
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        。。。
            # 提取文件后缀
            suffix = os.path.splitext(photo.filename)[1]
            # 生成随机文件名
            filename = random_string() + suffix
            # 保存文件
            photos.save(photo, name=filename)
        。。。
    
    • 生成缩略图:PIL模块(只支持py2,要支持py3需要安装pillow)
    from PIL import Image
    
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        ...
            # 拼接完整文件路径名
            pathname = os.path.join(app.config['UPLOADED_PHOTOS_DEST'], filename)
            # 打开文件
            img = Image.open(pathname)
            # 设置大小
            img.thumbnail((64, 64))
            # 保存图片
            img.save(pathname)
        ...
    

五.富文本编辑器

UEditor是由百度开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。帮助文档:http://fex-team.github.io/ueditor/

  • 下载(https://ueditor.baidu.com/website/download.html#ueditor)

    解压后,把ueditor放到static目录下

    | static/
    | | ueditor/
    | | |+dialogs/
    | | |+lang/
    | | |+php/
    | | |+themes/
    | | |+third-party/
    | | |-config.json
    | | |-index.html
    | | |-ueditor.all.js
    | | |-ueditor.all.min.js
    | | |-ueditor.config.js
    | | |-ueditor.parse.js
    | | |-ueditor.parse.min.js
    
  • 编辑模板文件

    在head标签加入下面几行:

    <script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='ueditor/ueditor.config.js') }}"></script>
    <script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='ueditor/ueditor.all.min.js') }}"> </script>
    <!--建议手动加在语言,避免在ie下有时因为加载语言失败导致编辑器加载失败-->
    <!--这里加载的语言文件会覆盖你在配置项目里添加的语言类型,比如你在配置项目里配置的是英文,这里加载的中文,那最后就是中文-->
    <script type="text/javascript" charset="utf-8" src="{{ url_for('static', filename='ueditor/lang/zh-cn/zh-cn.js') }}"></script>
    

    在body中加入:

    <script id="editor" type="text/plain"></script>
    
    <script type="text/javascript">
        //实例化编辑器
        //建议使用工厂方法getEditor创建和引用编辑器实例,如果在某个闭包下引用该编辑器,直接调用UE.getEditor('editor')就能拿到相关的实例
        var ue = UE.getEditor('editor', {
            serverUrl: "/upload/"
        });
    </script>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值