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 ...
随机推荐
- 20190322-a标签、img标签、三列表、特殊字符实体、表格
目录 1.a标签 a标签的属性 锚点 2.img标签 img标签的属性 图像热区 3.三列表 有序列表(Ordered List) ol>li 无序列表(Unordered List) ...
- HTML的概念和三大基石以及标准文档结构
HTML的概念: 概念: HTML:超文本标记语言 作用: 需要将java在后台根据用户请求处理的请求结果在浏览器中显示给用户. 在浏览器中数据需要使用友好的格式展示给用户. HTML是告诉浏 ...
- 小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别
for..in循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各个浏览器厂 ...
- Windows7 WIN 7 64位 环境编译6sv2.1版本的大气传输模型
从来没见过Fortran...这次为了添加国产卫星光谱响应的支持,只能从零开始肯了. 6S模型主页:http://6s.ltdri.org/index.html. 下载最新的2015年更新的6SV2. ...
- 从头认识一下docker-附带asp.net core程序的docker化部署
从头认识一下docker-附带asp.net core程序的docker化部署 简介 在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是 ...
- 基本的CRUD操作
导入包---实体类------数据库连接----数据库操作----service层数据操作----网页对service层可视化实现 model package com.ij34.model; publ ...
- ZYNQ EMIO使用及可重用封装
为了快速实现算法板级验证,PC端需要通过JTAG或以太网与FPGA形成通路.最简单便捷的方案是利用协议栈芯片,用户可以无视底层,利用简单的SPI协议读写寄存器实现复杂的TCP UDP等网络协议.当然带 ...
- mysql导出表的字段及相关属性
需要导出数据库中表的字段及属性,制成表格保存到word中 首先找到要导的库, 在查询页面输入sql SELECT COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE ...
- JS第二部分--DOM文档对象模型
一.DOM的概念 二.DOM可以做什么 三.DOM对象的获取 四.事件的介绍 五.DOM节点标签样式属性的操作 六.DOM节点对象对值的操作 七.DOM节点-标签属性的操作(例如id class sr ...
- gulp结合Thinkphp配置
gulpfile.js文件 /*! * gulp * $ npm install gulp gulp-ruby-sass gulp-cached gulp-uglify gulp-rename gul ...