Flask插件wtforms、Flask文件上传和Echarts柱状图
一、wtforms
类比Django的Form组件
Form组件的主要应用是帮助我们自动生成HTML代码和做一些表单数据的验证
flask的wtforms用法跟Form组件大同小异
参考文章:https://www.cnblogs.com/Zzbj/p/9966753.html
下载安装
pip install wtforms
1、wtforms使用介绍
1. wtforms支持的字段和验证函数
原文:https://blog.csdn.net/wuqing942274053/article/details/72510920
WTForms支持的HTML标准字段
字段类型 | 说明 |
---|---|
StringField | 文本字段 |
TextAreaField | 多行文本字段 |
PasswordField | 密码文本字段 |
HiddenField | 隐藏文本字段 |
DateField | 文本字段,值为datetime.date格式 |
DateTimeField | 文本字段,值为datetime.datetime格式 |
IntegerField | 文本字段,值为整数 |
DecimalField | 文本字段,值为decimal.Decimal |
FloatField | 文本字段,值为浮点数 |
BooleanField | 复选框,值为True和False |
RadioField | 一组单选框 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表,可选择多个值 |
FileField | 文件上传字段 |
SubmitField | 表单提交按钮 |
FormField | 把表单作为字段嵌入另一个表单 |
FieldList | 一组指定类型的字段 |
WTForms验证函数
验证函数 | 说明 |
---|---|
验证电子邮件地址 | |
EqualTo | 比较两个字段的值,常用于要求输入两次密码进行确认的情况 |
IPAddress | 验证IPv4网络地址 |
Length | 验证输入字符串的长度 |
NumberRange | 验证输入的值在数字范围内 |
Optional | 无输入值时跳过其他验证函数 |
Required | 确保字段中有数据 |
Regexp | 使用正则表达式验证输入值 |
URL | 验证URL |
AnyOf | 确保输入值在可选值列表中 |
NoneOf | 确保输入值不在可选列表中 |
2. wtforms类的属性和方法
属性:
data
包含每个字段的数据的字典
errors
包含每个字段的错误列表的DECT。如果没有验证表单,或者没有错误,则为空。
meta
这是一个包含各种配置选项以及自定义表单行为的能力的对象。有关可以使用类元选项自定义的内容的更多信息,请参见类元文档。
方法:
validate():通过在每个字段上调用Value来验证表单,将任何额外的Form.Value_<field name>验证器传递给字段验证器。
populate_obj(obj):使用表单字段中的数据填充传递的obj的属性。
__iter__():按创建顺序迭代表单字段。
__contains__(name):如果指定的字段是此表单的成员,则返回True。
例如:
- form_obj = wtform(request.form)
- if form_obj.validate():
- # 包含每个字段的数据的字典
- print(form_obj.data)
- # 这是一个包含各种配置选项以及自定义表单行为的能力的对象
- print(form_obj.meta)
- return "注册成功"
- # 包含每个字段的错误列表的DECT。如果没有验证表单,或者没有错误,则为空。
- print(form_obj.errors)
字段的基类:
label | 字段的标签 |
validators | 验证器 -验证的序列时要调用验证被调用 |
default | 如果未提供表单或对象输入,则分配给字段的默认值 |
widget | 如果提供,则覆盖用于呈现字段的窗口小部件 |
render_kw | 设置字段的额外参数,提供一个字典 |
filters | 按进程在输入数据上运行的一系列过滤器。 |
description | 字段的描述,通常用于帮助文本 |
id | 用于字段的id。表单设置了合理的默认值,您不需要手动设置。 |
_form | 包含此字段的表单。在施工期间,它由表格本身传递。你永远不应该自己传递这个值。 |
_name | 此字段的名称,由封闭表单在构造期间传递。你永远不应该自己传递这个值 |
_prefix | 前缀为此字段的表单名称的前缀,在构造期间由封闭表单传递。 |
_translations | 提供消息翻译的翻译对象。通常在施工期间通过封闭的形式通过。 |
_meta | 如果提供,这是表单中的'meta'实例。你通常不会自己通过 |
2、基本的使用
1. MyForms.py 定义Form表单的类
- from wtforms import Form, widgets
- from wtforms.fields import simple, core, html5
- # 使用wtforms的类必须要继承它的Form类
- # simple:普通字段 core:核心字段 html5:H5新增的字段
- class RegisterForm(Form):
- username = simple.StringField(
- label='用户名',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- # widget插件,可以把这个字段设置成其他type类型
- widget=widgets.TextArea()
- )
- pwd = simple.PasswordField(
- label='密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'}
- )
- re_pwd = simple.PasswordField(
- label='确认密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- )
2. 视图
- from flask import Blueprint, render_template
- from FlaskPlug.utils.MyForms import RegisterForm
- userBlue = Blueprint("userBlue", __name__)
- @userBlue.route('/register')
- def register():
- # 实例化form
- form_obj = RegisterForm()
- return render_template('register.html', form_obj=form_obj)
3. HTML代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>注册</title>
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
- </head>
- <body>
- <div class="container">
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- <h2 style="margin-top: 50px;margin-bottom: 30px;text-align: center">欢迎注册</h2>
- <form action="" method="POST" novalidate class="form-horizontal">
- {% for field in form_obj %}
- <div class="form-group">
- {{ field.label }}
- {{ field }}
- </div>
- {% endfor %}
- <button type="submit" class="btn btn-success">提交</button>
- </form>
- </div>
- </div>
- </div>
- </body>
- </html>
3、验证
3-1、基本验证
步骤
1. 在Form类中增加验证信息
2. 在视图中做数据的校验 并且页面展示错误信息
1. MyForms.py 定义Form表单的类
- from wtforms import Form, widgets, validators
- from wtforms.fields import simple, core, html5
- class RegisterForm(Form):
- username = simple.StringField(
- label='用户名',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- # 可以定义多个校验规则
- validators=[
- # DataRequired字段必填
- validators.DataRequired(message='用户名不能为空'),
- # length字段的长度限制
- # message:用户填写错误时的错误信息
- validators.length(min=2, max=8, message='长度必须在2-8之间')
- ],
- # widget=widgets.TextArea()
- )
- pwd = simple.PasswordField(
- label='密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间')
- ],
- )
- re_pwd = simple.PasswordField(
- label='确认密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间'),
- # EqualTo:校验两个字段的值是否相等
- validators.EqualTo('pwd', message='两次密码不一致')
- ],
- )
- phone = simple.StringField(
- label='手机号码',
- validators=[
- validators.Regexp(regex="^1[3-9][0-9]{9}$",message='手机格式不正确')
- ]
- )
2. 视图
- from flask import Blueprint, render_template, request
- from FlaskPlug.utils.MyForms import RegisterForm
- from FlaskPlug.models import User
- userBlue = Blueprint("userBlue", __name__)
- @userBlue.route('/register', methods=['GET', 'POST'])
- def register():
- # 实例化form
- form_obj = RegisterForm()
- if request.method == "POST":
- # 把用户提交上来的数据放入Form表单中实例化
- form_obj = RegisterForm(request.form)
- # validate方法会去校验用户提交上来的数据
- if form_obj.validate():
- # 验证通过可以写入数据库,这里演示,不写入
- # 验证通过的数据都保存在data这个大字典里面
- # username = form_obj.data.get('username')
- # password = form_obj.data.get('pwd')
- # user_obj = User(username=username, password=password)
- # db.session.add(user_obj)
- # db.session.commit()
- # db.session.close()
- return "注册成功"
- return render_template('register.html', form_obj=form_obj)
3. HTML代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>注册</title>
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
- </head>
- <body>
- <div class="container">
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- <h2 style="margin-top: 50px;margin-bottom: 30px;text-align: center">欢迎注册</h2>
- <form action="" method="POST" novalidate class="form-horizontal">
- {% for field in form_obj %}
- <div class="form-group">
- {{ field.label }}
- {{ field }} <span style="color: red">{{ field.errors[0] }}</span>
- </div>
- {% endfor %}
- <button type="submit" class="btn btn-success">提交</button>
- </form>
- </div>
- </div>
- </div>
- </body>
- </html>
3-2、自定义校验规则
- from wtforms import Form, validators, ValidationError
- from wtforms.fields import simple
- def check_username(form, field):
- if len(field.data) < 2:
- raise ValidationError('错了,嘿嘿')
- class TestForm(Form):
- username = simple.StringField(
- label='用户名',
- validators=[check_username, ]
- )
3-3、利用钩子函数进行校验
- 局部钩子函数: validate_字段名,接收两个参数(form, field),后端调用validate()校验函数的时候触发
- form: wtforms类的实例
- field: 字段对象,可以通过field.data获取前端传过来的该字段的数据,不是字典
- 全局钩子函数:validate, 接收self参数,self.data代表前端表单传过来的所有数据,是一个字典
- from wtforms import Form, validators, ValidationError
- from wtforms.fields import simple
- class TestForm(Form):
- username = simple.StringField(
- label='用户名',
- )
- password = simple.PasswordField(
- label='密码',
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间')
- ]
- )
- # 局部钩子函数
- def validate_username(form, field):
- print(field.data) # 张三
- if len(field.data) < 2:
- raise ValidationError('用户名至少两位字符')
- # 全局钩子函数
- def validate(self):
- print(self.data) # {'username': '张三', 'password': '12345678'}
- for key, value in self.data.items():
- print(value)
4、拓展字段core/html5
- from wtforms import Form, widgets, validators
- from wtforms.fields import simple, core, html5
- class RegisterForm(Form):
- username = simple.StringField(
- label='用户名',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- # 可以定义多个校验规则
- validators=[
- # DataRequired字段必填
- validators.DataRequired(message='用户名不能为空'),
- # length字段的长度限制
- # message:用户填写错误时的错误信息
- validators.length(min=2, max=8, message='长度必须在2-8之间')
- ],
- # widget=widgets.TextArea()
- )
- pwd = simple.PasswordField(
- label='密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间')
- ],
- )
- re_pwd = simple.PasswordField(
- label='确认密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间'),
- # EqualTo:校验两个字段的值是否相等
- validators.EqualTo('pwd', message='两次密码不一致')
- ],
- )
- phone = simple.StringField(
- label='手机号码',
- validators=[
- validators.Regexp(regex="^1[3-9][0-9]{9}$",message='手机格式不正确')
- ]
- )
- # H5新增的标签email
- email = html5.EmailField(
- label='邮箱',
- validators=[
- validators.DataRequired(message='邮箱不能为空.'),
- ],
- widget=widgets.TextInput(input_type='email'),
- )
- # 核心字段core,单选框
- gender = core.RadioField(
- label='性别',
- choices=((1, '男'), (2, '女')),
- # 前端传过来的数据是字符串类型,coerce可以把穿过来的数据转换类型
- # 因为数据库存的1是int类型,前端选择"男",传过来的是字符串1
- coerce=int,
- default=1
- )
- # 单选下拉菜单
- city = core.SelectField(
- label='城市',
- choices=(('sz', '深圳'), ('gz', '广州'), )
- )
- # 多选下拉菜单
- hobby = core.SelectMultipleField(
- label='爱好',
- choices=(
- (1, '美女'),
- (2, 'xiong'),
- ),
- )
- favor = core.SelectMultipleField(
- label='喜好',
- choices=(
- (1, '篮球'),
- (2, '足球'),
- ),
- # 把多选下拉菜单设置成列表
- widget=widgets.ListWidget(prefix_label=False),
- option_widget=widgets.CheckboxInput(),
- coerce=int,
- default=[1, 2]
- )
- def __init__(self, *args, **kwargs):
- super(RegisterForm, self).__init__(*args, **kwargs)
- # 从数据库获取数据 做到实时更新
- # self.favor.choices = ORM操作
- # 这里演示一下更改
- self.favor.choices = ((1, '篮球'), (2, '足球'), (3, '羽毛球'))
5、实现csrf_token
1.Form类
- from flask import request
- from wtforms import Form
- from wtforms.csrf.core import CSRF
- from wtforms.fields import simple
- from wtforms import validators
- from wtforms import widgets
- from hashlib import md5
- # 自定义CSRF类,重写CSRF的三个方法
- class MyCSRF(CSRF):
- """
- Generate a CSRF token based on the user's IP. I am probably not very
- secure, so don't use me.
- """
- def setup_form(self, form):
- # 获取class Meta里设置的一些值
- self.csrf_context = form.meta.csrf_context()
- self.csrf_secret = form.meta.csrf_secret
- # 调用父类的setup_form方法
- return super(MyCSRF, self).setup_form(form)
- def generate_csrf_token(self, csrf_token):
- # 使用md5加密,生成唯一token
- gid = self.csrf_secret + self.csrf_context
- token = md5(gid.encode('utf-8')).hexdigest()
- return token
- def validate_csrf_token(self, form, field):
- # 校验token
- print(field.data, field.current_token)
- if field.data != field.current_token:
- raise ValueError('Invalid CSRF')
- class RegisterForm(Form):
- username = simple.StringField(
- label='用户名',
- render_kw={'class': 'form-control'},
- widget=widgets.TextInput(),
- validators=[
- validators.DataRequired(message='用户名不能为空'),
- validators.length(min=2, max=8, message='长度必须在2-8之间')
- ]
- )
- password = simple.PasswordField(
- label='密码',
- render_kw={'class': 'form-control'},
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间')
- ]
- )
- re_pwd = simple.PasswordField(
- label='确认密码',
- # 给这个字段添加样式
- render_kw={'class': 'form-control'},
- validators=[
- validators.DataRequired(message='密码不能为空'),
- validators.length(min=8, max=16, message='长度必须在8-16之间'),
- validators.EqualTo('password', message='两次密码不一致')
- ]
- )
- phone = simple.StringField(
- label='手机号码',
- validators=[
- validators.Regexp(regex="^1[3-9][0-9]{9}$", message='手机格式不正确')
- ]
- )
- class Meta:
- # -- CSRF
- # 是否自动生成CSRF标签
- csrf = True
- # 生成CSRF标签name
- csrf_field_name = 'csrf_token'
- # 自动生成标签的值,加密用的csrf_secret
- csrf_secret = '一库'
- # 自动生成标签的值,加密用的csrf_context
- csrf_context = lambda x: request.url
- # 生成和比较csrf标签
- csrf_class = MyCSRF
- # -- i18n
- # 是否支持本地化
- # locales = False
- locales = ('zh', 'en')
- # 是否对本地化进行缓存
- cache_translations = True
- # 保存本地化缓存信息的字段
- translations_cache = {}
2.models
- class User(db.Model):
- __tablename__ = 'user'
- id = db.Column(db.Integer, primary_key=True)
- username = db.Column(db.String(32), nullable=False)
- password = db.Column(db.String(32), nullable=False)
- phone = db.Column(db.String(32))
3.视图
- from flask import request, views, session, render_template
- from flask_demo.home.models.home_model import *
- from flask_demo import db
- from flask_demo.home.forms.home_forms import RegisterForm
- class RegisterView(views.MethodView):
- def get(self):
- form_obj = RegisterForm()
- return render_template('register.html', form_obj=form_obj)
- def post(self):
- form_obj = RegisterForm(request.form)
- if form_obj.validate():
- user_dict = {}
- user_dict['username'] = form_obj.data.get('username')
- user_dict['password'] = form_obj.data.get('password')
- user_dict['phone'] = form_obj.data.get('phone')
- user_obj = User(**user_dict)
- db.session.add(user_obj)
- db.session.commit()
- db.session.close()
- return "注册成功"
- return render_template('register.html', form_obj=form_obj)
4.HTML代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>注册</title>
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css">
- </head>
- <body>
- <div class="container">
- <div class="row">
- <div class="col-md-4 col-md-offset-4">
- <h2 style="margin-top: 50px;margin-bottom: 30px;text-align: center">欢迎注册</h2>
- <form action="" method="POST" novalidate class="form-horizontal">
- {{ form_obj.csrf_token }}
- <div class="form-group">
- {{ form_obj.username.label }}
- {{ form_obj.username }}
- <span style="color: red">{{ form_obj.username.errors[0] }}</span>
- </div>
- <div class="form-group">
- {{ form_obj.password.label }}
- {{ form_obj.password }}
- <span style="color: red">{{ form_obj.password.errors[0] }}</span>
- </div>
- <div class="form-group">
- {{ form_obj.re_pwd.label }}
- {{ form_obj.re_pwd }}
- <span style="color: red">{{ form_obj.re_pwd.errors[0] }}</span>
- </div>
- <div class="form-group">
- {{ form_obj.phone.label }}
- {{ form_obj.phone }}
- <span style="color: red">{{ form_obj.phone.errors[0] }}</span>
- </div>
- <button type="submit" class="btn btn-success">提交</button>
- </form>
- </div>
- </div>
- </div>
- </body>
- </html>
二、基于Flask的文件上传Demo
- """
- 文件上传完后,进行代码的统计
- app.config.root_path: 项目的根路径
- os.walk:
- 遍历你给的路径下的所有文件(会递归遍历)
- 每次循环的根文件夹的路径,文件夹的名字组成的列表,和文件组成的列表
- dirpath, dirnames, filenames
- zipfile: 压缩解压文件的模块
- shutil: 也是压缩解压文件的模块,还能移动啥的
- """
- from flask import Blueprint, request, render_template
- from flask import current_app as app
- import shutil
- from uploadCode.models import CodeRecord
- from uploadCode import db
- import os
- import time
- uploadBlue = Blueprint('uploadBlue', __name__)
- # zip包上传
- @uploadBlue.route('/upload', methods=['GET', 'POST'])
- def upload():
- if request.method == "GET":
- return render_template("upload.html", error="")
- # 先获取前端传过来的文件
- file = request.files.get("zip_file")
- # 判断是否是zip包
- zip_file_type = file.filename.rsplit(".", 1)
- if zip_file_type[-1] != "zip":
- return render_template("upload.html", error="文件必须是zip包")
- # 解压路径
- upload_path = os.path.join(app.config.root_path, "files", zip_file_type[0]+str(time.time()))
- print(upload_path)
- # 解压前端传过来的文件file到upload_path这个路径
- shutil._unpack_zipfile(file, upload_path)
- # 遍历保存的文件夹得到所有.py文件
- file_list = []
- for (dirpath, dirnames, filenames) in os.walk(upload_path):
- for filename in filenames:
- file_type = filename.rsplit(".", 1)
- if file_type[-1] != "py":
- continue
- file_path = os.path.join(dirpath, filename)
- file_list.append(file_path)
- # 打开每个文件读取行数
- sum_num = 0
- for path in file_list:
- with open(path, mode="rb") as f:
- for line in f:
- if line.strip().startswith(b"#"):
- continue
- sum_num += 1
- # 得到总行数去保存数据库
- return str(sum_num)
1. upload.py
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <form action="" method="post" enctype="multipart/form-data">
- 请上传你的代码: <input type="file" name="zip_file">
- <button type="submit">提交</button>
- {{error}}
- </form>
- </body>
- </html>
2. HTML代码
三、柱状图
参考文档Echarts:http://echarts.baidu.com/
1、使用Echarts步骤
1. 下载它需要的依赖包
2. 点击某个Demo-->Download
3. 参考着Demo去实现你的需求
2、注意
从后端传数据到前端的时候,因为展示的柱状图需要后端的数据,
而如果把数据直接在JS中使用,会出现一些问题,
因此,我们可以使用一个标签,给这个标签设置属性从而获取从后端传过来的数据,
然后在JS中获取这个标签的属性值,就可以拿到后端的数据了,
但是从属性获取的数据已经被转化成字符串了,我们这时可以使用eval()方法,
把数据类型重新转换回来。
3、Demo
- from flask import Blueprint, request, render_template
- from uploadCode.models import CodeRecord
- from uploadCode import db
- # 柱状图
- @uploadBlue.route("/")
- def index():
- # 展示用户提交代码柱状图
- queryset = db.session.query(CodeRecord).all()
- date_list = []
- num_list = []
- for obj in queryset:
- date_list.append(str(obj.upload_date))
- num_list.append(obj.code_nums)
- return render_template("index.html", date_list=date_list, num_list=num_list)
1. Demo.py
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <script src="/static/echarts.common.min.js"></script>
- </head>
- <body>
- <div id="container" style="height: 400px"></div>
- <!--用一个标签获取从后端传过来的数据-->
- <div id="info" date_list="{{date_list}}" num_list="{{num_list}}"></div>
- <script>
- var dom = document.getElementById("container");
- var myChart = echarts.init(dom);
- var app = {};
- let infoEle = document.getElementById("info");
- let date_list = infoEle.getAttribute("date_list");
- let num_list = infoEle.getAttribute("num_list");
- option = null;
- app.title = '坐标轴刻度与标签对齐';
- option = {
- color: ['#3398DB'],
- tooltip : {
- trigger: 'axis',
- axisPointer : { // 坐标轴指示器,坐标轴触发有效
- type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
- }
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true
- },
- xAxis : [
- {
- type : 'category',
- data : eval(date_list),
- axisTick: {
- alignWithLabel: true
- }
- }
- ],
- yAxis : [
- {
- type : 'value'
- }
- ],
- series : [
- {
- name:'直接访问',
- type:'bar',
- barWidth: '60%',
- data: eval(num_list) // 重新计算一下这个字符串,转成原本的数据类型
- }
- ]
- };
- ;
- if (option && typeof option === "object") {
- myChart.setOption(option, true);
- }
- </script>
- </body>
- </html>
2. HTML代码(根据官方Demo修改一下)
Flask插件wtforms、Flask文件上传和Echarts柱状图的更多相关文章
- 【Flask】 结合wtforms的文件上传表单
表单中的文件上传 基本的表单渲染,表单类设置等等就不多说了,参看另一个文章即可.但是那篇文章里没有提到对于FileField,也就是上传文件的表单字段是如何处理,后端又是如何实现接受上传过来的文件的. ...
- flask插件系列之flask_uploads上传文件
前言 flask可以实现上传文件和下载文件的基本功能,但如果想要健壮的功能,使用flask_uploads插件是十分方便的. 安装 pip install flask_uploads 基本使用 # e ...
- 结合bootstrap fileinput插件和Bootstrap-table表格插件,实现文件上传、预览、提交的导入Excel数据操作流程
1.bootstrap-fileinpu的简单介绍 在前面的随笔,我介绍了Bootstrap-table表格插件的具体项目应用过程,本篇随笔介绍另外一个Bootstrap FieInput插件的使用, ...
- HTML5文件上传器,纯脚本无插件的客户端文件上传器---Uploader 文件上传器类
概述 客户端完全基于JavaScript的 浏览器文件上传器,不需要任何浏览器插件,但需要和jQuery框架协同工作,支持超大文件上传,其算法是将一个超大文件切片成N个数据块依次提交给服务 端处理,由 ...
- ajaxFileUpload.js插件支持多文件上传的方法
前提条件:ajaxFileUpload.js插件多文件上传步骤:1.修改源码,(源码只支持单个文件的上传):复制代码 代码如下: //修改前代码------- //var oldElement = j ...
- BootStrap FileInput 插件实现多文件上传前端功能
<!DOCTYPE html> <html> <head> <title>文件上传</title> <meta charset=&qu ...
- 使用flask实现简单的文件上传
from flask import Flask, redirect, render_template, request, url_forfrom werkzeug.utils import secur ...
- ajax+php (jquery.form插件)实现异步文件上传
<!DOCTYPE html> <html lang="CN"> <head> <title>upload model</ti ...
- flask完成文件上传功能
在使用flask定义路由完成文件上传时,定义upload视图函数 from flask import Flask, render_template from werkzeug.utils import ...
随机推荐
- js之正则的坑
首先给一个神奇的图: 我的反应,精分吧!一会儿true一会儿false的... 后来发现,把g去掉后就正常了,那这是为什么呢??lastIndex惹得鬼! 正文: lastIndex 全局正则表达是, ...
- 小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别
for..in循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各个浏览器厂 ...
- #WEB安全基础 : HTML/CSS | 0x5a标签拓展和class、id属性的使用
a标签不只是能链接到其他网页,也能链接到网页中的元素 class属性让你用CSS对特定的元素进行修饰 这些是一个网页设计者的有力武器 这节课还是一个index.html文件 以下是代码 <h ...
- arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- Numpy数组数据文件的读写
一.引言 读写数据文件的重要性就不必多说了. 二.读取列表形式数据的文件 1.我们写几行CSV格式(列表形式,两值之间逗号隔开)的数据. id,height,age 1,175,20 2,168,18 ...
- 从.Net到Java学习第六篇——SpringBoot+mongodb&Thymeleaf&模型验证
SpringBoot系列目录 SpringBoot整合mongodb MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.如果你没用过Mong ...
- jupyter notebook安装、登录
pip install jupyter 提示pip需要升级(本人装的是anaconda) 输入:python -m pip install --upgrade pip 安装完成. 运行jupyter ...
- 解决 winform打开网页 和WebBrowser打开链接360误报拦截的问题
以下方法我已经在自己电脑上验证通过,其他电脑并未测试,请广大读者自行验证并反馈,如果有更好的方法请指教. 在winform中如果使用这种方法弹出网页,例如这样 Process.start(" ...
- Tomcat安装教程
Tomcat安装教程 文档下载:https://files-cdn.cnblogs.com/files/yocichen/Tomcat安装教程.rar 注意:本教程适用Windows平台安装Tomca ...
- 如何让EasyUI的Tree或者ComboTree节点不显示图标?
版本:jQuery EasyUI 1.3.2 通过测试,只需把节点的state属性设置为null即可使EasyUI的Tree或者ComboTree控件的节点不显示图标.