Python全栈工程师之从网页搭建入门到Flask全栈项目实战(6) - Flask表单的实现
1.表单介绍
1.1.表单知识回顾
常见的表单元素:
- 表单标签<form>
- action:表单提交的URL地址
- method:表单请求的方式(GET/POSt)
- enctype:请求内容的形式,如:application/x-www-form-urlencoded、multipart/form-data
- 单行文本框/多行文本框
- textarea:多行文本
- 单行文本(type的不同值),常见的有:text(单行文本)、password(密码)、email(邮箱)、url(URL)、number(数字)、color(颜色)、日期时间等(date、month、week等等)
- 选择(单选、多选、下拉选择)
- 单选: <input type="radio">
- 多选: <input type="checkbox">
- 下拉框选择: <select><option></option></select>
- 隐藏表单域: <input type="hidden">
- 表单按钮: <input type="button"> <button></button>
- 文件上传框: <input type="file">
- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>表单知识点回顾</title>
- 6 </head>
- 7 <body>
- 8 <form action="/index" method="post" enctype="multipart/form-data">
- 9 <ul>
- 10 <li>
- 11 用户地址:
- 12 <textarea name="" id="" cols="30" rows="10" placeholder="请输入地址"></textarea>
- 13 </li>
- 14 <li>
- 15 用户名:
- 16 <input type="text" placeholder="请输入用户名">
- 17 </li>
- 18 <li>
- 19 密码:
- 20 <input type="password" placeholder="请输入密码">
- 21 </li>
- 22 <li>
- 23 用户的年龄:
- 24 <input type="number">
- 25 </li>
- 26 <li>
- 27 性别:
- 28 <label><input type="radio" value="男" name="sex">男</label>
- 29 <label><input type="radio" value="女" name="sex">女</label>
- 30 </li>
- 31 <li>
- 32 爱好
- 33 <input id="id-paly-ball" type="checkbox" value="打球">
- 34 <label for="id-paly-ball">打球</label>
- 35 <input id="id-paly" type="checkbox" value="玩耍">
- 36 <label for="id-paly">玩耍</label>
- 37 </li>
- 38 </ul>
- 39 </form>
- 40 </body>
- 41 </html>
在视图中获取表单值:
- get请求: request.args.get('name',None)
- post请求: request.form.get('name',None)
思考:HTML表单在Flask中如何快速使用?
1.2.wtf表单介绍
通过在Flask中写python代码,可以直接生成HTML表单,通过wtf实现。
flask-wtf提供的3个组要功能:
- 集成wtforms
- CSRF保护,flask-wtf能保护所有表单免受跨站请求伪造(CSRF)的攻击
- 与Flask-Uploads一起支持文件上传
安装
- pip安装: pip install Flask-WTF
- 源码安装: python setup.py install
下载好之后如何使用呢?需不需要一些配置呢?它的配置很简单,它配置的目的就是用来做CSRF保护。只需要在Flask app上加上 WTF_CSRF_SECRET_KEY = 'a random string' 就行了,这个key可以随便给一个字符串,没有要求,只是一个随机的串就行了。
- 1 from flask import Flask, render_template,flash
- 2 from flask_sqlalchemy import SQLAlchemy
- 3
- 4 app = Flask(__name__)
- 5 # 配置数据库的连接参数
- 6 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:@127.0.0.1/test_flask'
- 7 app.config['SECRET_KEY'] = 'abc' #消息闪现保护的key,注意当消息闪现的SECRET_KEY配置了,WTF_CSRF_SECRET_KEY也可以不用配置,但是你配置了也没有影响,这个知识点了解一下
- 8 app.config['WTF_CSRF_SECRET_KEY'] = 'abc1234abc' #WTF_CSRF_SECRET_KEY配置
第一个表单模型
- 1 from flask_wtf import FlaskForm #导入flask_wtf的FlaskForm类
- 2 from wtforms import StringField #StringField表示的是一个文本的输入框
- 3
- 4
- 5 class LoginForm(FlaskForm): #继承FlaskForm类
- 6 """ 登录表单的实现 """
- 7 username = StringField(label='用户名')
1.3.表单常用字段类型及渲染
表单常用字段类型
- 文本/字符串
- StringField :字符串输入
- PasswordField :密码输入
- TextAreaField :长文本输入
- HiddenField :隐藏表单域
- 数值(整数,小数)
- FloatField :浮点数输入
- IntegerField :整数输入
- DecimalField :小数输入(更准确)
- 选择
- RadioFied :radio单选
- SelectField :下拉单选
- SelectMultipleField :下拉多选
- BooleanField :勾选(复选框)
- 日期/时间
- DateField :日期选择
- DateTimeField :日期时间选择
- 文件/文件上传
- FileField :文件单选
- MultipleFileField :文件多选
- 其他
- SubmitField :提交按钮
- FieldList :自定义的表单选择列表(如:选择用户对象)
- FormField :自定义多个字段构成的选项
表单字段的常用核心参数
- lable :lable标签(如:输入框钱的文字描述)
- default :表单的默认值
- validators :表单验证规则
- widget :定制界面显示方式(如:文本框、选择框)
- description :帮助文字
表单渲染
使用模板语法渲染表单内容:
- 表单输入区域: {{form.username}}
- 表单label: {{form.username.label}}
实例代码:
forms.py:python编写登录表单页面导入FlaskForm,wtfforms实现
- 1 from flask_wtf import FlaskForm
- 2 from wtforms import StringField, PasswordField, SubmitField
- 3
- 4
- 5 class LoginForm(FlaskForm):
- 6 """ 登录表单的实现 """
- 7 username = StringField(label='用户名', default='admin')
- 8 password = PasswordField(label='密码')
- 9 submit = SubmitField('登录')
app.py:导入forms文件,将python编写好的HTML页面展示类传递给html文件
- 1 from flask import Flask, render_template
- 2
- 3 from forms import LoginForm
- 4
- 5 app = Flask(__name__)
- 6 app.config['WTF_CSRF_SECRET_KEY'] = 'abc1234abc'
- 7 app.config['SECRET_KEY'] = 'abc'
- 8
- 9
- 10 @app.route('/form', methods=['GET', 'POST'])
- 11 def page_form():
- 12 """ form 表单练习 """
- 13 form = LoginForm()
- 14 return render_template('page_form.html', form=form)
page_form.html
- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>Flask Form表单练习</title>
- 6 </head>
- 7 <body>
- 8 <h3>欢迎登录</h3>
- 9 <form action="" method="post">
- 10 <p>
- 11 {{ form.username.label }}
- 12 {{ form.username }}
- 13 </p>
- 14 <p>
- 15 {{ form.password.label }}
- 16 {{ form.password }}
- 17 </p>
- 18 <p>
- 19 {{ form.submit }}
- 20 </p>
- 21
- 22 </form>
- 23 </body>
- 24 </html>
1.4.通过表单保存数据
保单保存数据步骤:
- 第一步:检测表单是否已经通过验证
- form.validate_on_submit()
- 第二步:获取表单中传递过来的值
- form.field_name.data
- 第三步:业务逻辑代码编写(结合ORM)
表单保存数据的时候会触发CSRF表单保护:
- 默认模板是开启CSRF保护
- 关闭单个表单CSRF保护
- form = LoginForm(csrf_enabled=False)
- 全局关闭(不推荐)
- 在类上面加上:WTF_CSRF_ENABLED=False
如果不关闭CSRF保护,如何处理:
同步请求CSRF保护,在模板中添加csrf_token,通过CSRF机制的验证:
- 方式一:{{ form.csrf_token }}
- 方式二:<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
实例代码:
新增用户注册表单,对注册的内容进行入库,注册成功后返回index主页面。
app.py
- 1 from flask import Flask, render_template, flash, redirect, url_for
- 2 from flask_sqlalchemy import SQLAlchemy
- 3
- 4 from forms import RegisterForm
- 5
- 6 app = Flask(__name__)
- 7 # 配置数据库的连接参数
- 8 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:@********/test_flask'
- 9 app.config['WTF_CSRF_SECRET_KEY'] = 'abc1234abc'
- 10 app.config['SECRET_KEY'] = 'abc'
- 11 db = SQLAlchemy(app)
- 12
- 13
- 14 class User(db.Model):
- 15 __tablename__ = 'weibo_user'
- 16 id = db.Column(db.Integer, primary_key=True)
- 17 username = db.Column(db.String(64), nullable=False)
- 18 password = db.Column(db.String(256), nullable=False)
- 19 birth_date = db.Column(db.Date, nullable=True)
- 20 age = db.Column(db.Integer, default=0)
- 21
- 22 @app.route('/')
- 23 def index():
- 24 """ 首页 """
- 25 return render_template('index.html')
- 26
- 27 @app.route('/user/register', methods=['GET', 'POST'])
- 28 def page_register():
- 29 """ 新用户注册 """
- 30 # csrf_enabled为False表示不做csrf校验
- 31 # form = RegisterForm(csrf_enabled=False)
- 32 form = RegisterForm()
- 33 # 用户在提交表单的时候,会触发validate_on_submit
- 34 if form.validate_on_submit():
- 35 # 表单验证通过,接下来处理业务逻辑
- 36 # 1. 获取表单数据
- 37 username = form.username.data
- 38 password = form.password.data
- 39 birth_date = form.birth_date.data
- 40 age = form.age.data
- 41 # 2. 构建用户对象
- 42 user = User(
- 43 username=username,
- 44 password=password,
- 45 birth_date=birth_date,
- 46 age=age
- 47 )
- 48 # 3. 提交到数据库
- 49 db.session.add(user)
- 50 db.session.commit()
- 51 print('添加成功')
- 52 # 4. 跳转到登录页面
- 53 return redirect(url_for('index'))
- 54 else:
- 55 # 打印错误信息
- 56 print(form.errors)
- 57 return render_template('page_register.html', form=form)
forms.py
- 1 from flask_wtf import FlaskForm
- 2 from wtforms import StringField, PasswordField, SubmitField, DateField, IntegerField
- 3
- 4
- 5 class RegisterForm(FlaskForm):
- 6 """ 用户注册表单 """
- 7
- 8 # def __init__(self, csrf_enabled, *args, **kwargs):
- 9 # super().__init__(csrf_enabled=csrf_enabled, *args, **kwargs)
- 10
- 11 username = StringField(label='用户名', default='')
- 12 password = PasswordField(label='密码')
- 13 birth_date = DateField(label='生日')
- 14 age = IntegerField(label='年龄')
- 15 submit = SubmitField('注册')
page_register.html
- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>用户注册</title>
- 6 </head>
- 7 <body>
- 8 <h3>用户注册</h3>
- 9 {# todo 注释内容:使用宏来把表单进一步完善 #}
- 10 <form action="{{ url_for('page_register') }}" method="post">
- 11 {{ form.csrf_token }}
- 12 <p>
- 13 {{ form.username.label }}
- 14 {{ form.username }}
- 15 </p>
- 16 <p>
- 17 {{ form.password.label }}
- 18 {{ form.password }}
- 19 </p>
- 20 <p>
- 21 {{ form.birth_date.label }}
- 22 {{ form.birth_date }}
- 23 </p>
- 24 <p>
- 25 {{ form.age.label }}
- 26 {{ form.age }}
- 27 </p>
- 28 <p>
- 29 {{ form.submit }}
- 30 </p>
- 31
- 32 </form>
- 33 </body>
- 34 </html>
index.html
- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>用户首页</title>
- 6 </head>
- 7 <body>
- 8 注册成功
- 9 </body>
- 10 </html>
2.表单验证与图片上传
2.1.表单验证
思考:以手机注册为例,不验证表单会怎么样?
- 用户输入的可能不是手机号
- 用户输入的可能不是他的手机号
- 不断的提交表单
思考:表单验证为了什么?
- 更好的用户体验
- 更少的安全隐患
- 永远不要相信用户的输入
内置的表单验证器
- DataRequired/InputRequired :必填验证
- Email/URL/UUID :电子邮箱/URL/UUID格式验证
- Length(min=-1,max=-1,message=None) :长度范围验证
- EqualTo(fieldname,message=None) :重复验证,用于密码的二次输入验证和上一次是否一致
自定义表单验证
- 场景一:只有本表单使用,在表单类里面创建一个方法,方法名为:validatge_需要验证的变量,在方法中编写验证逻辑
- 场景二:多个表单中使用,如:验证手机号码,登录/注册/修改用户信息页面均会用到。在表单类外面声明一个验证方法,传入form对象。这个方法命名就没有要求,这个见示例代码。
图为场景一的示例,场景二跟这个差不多;两者的区别主要在于一个放到类里面,一个放到类外面;备注:方法命名的规则暂时这么理解,我学的好像是这样的,我是这么理解的,有知道所以然的可以教下我,谢谢!
实例:
场景一(当前表单使用):
- 1 import re
- 2
- 3 from flask_wtf import FlaskForm
- 4 from wtforms import StringField, PasswordField, SubmitField, DateField, IntegerField
- 5 from wtforms.validators import DataRequired,ValidationError
- 6
- 7 class RegisterForm(FlaskForm):
- 8 """ 用户注册表单 """
- 9
- 10 username = StringField(label='用户名', default='')
- 11 password = PasswordField(label='密码',validators=[DataRequired("请输入密码")]) #增加必填验证
- 12 birth_date = DateField(label='生日')
- 13 age = IntegerField(label='年龄')
- 14 submit = SubmitField('注册')
- 15
- 16 def validate_username(self,field): #注意这个方法必须是validate_*****
- 17 """ 验证用户名 """
- 18 # 自定义:强制验证用户名为手机号
- 19 username = field.data
- 20 pattern = r'^1[0-9]{10}$' #自定义正则匹配规则
- 21 if not re.search(pattern,username):
- 22 raise ValidationError('请输入手机号码')
- 23 return field
我们看到报错提示信息是在控制台展示的,那么我们怎么让提示信息展示给用户?
forms.py文件里面自定义了表单验证规则,验证失败抛出form的错误
app.py文件无法提交时,将打印form文件抛出的异常.。异常内容为 {'username': ['请输入手机号码']} 是个items结构。
前端页面,获取forms的username的报错信息,进行展示
场景二(多个表单使用):
图froms.py:用python编写登录的前端页面、表单自定义的验证、表单字段使用自定义的验证
疑问:在类外面自定义的验证方法,为什么要传form,不传行不行;不穿form就会报错,说应该传两个参数,只传了一个,那这是为什么呢?
看了系统自带验证规则的源码,发现都是两个形参form和field,就暂时这么理解吧:因为源码有,跟他保持一致,form具体干什么使的后面研究了再说吧!
图app.py启动文件:将登录页面forms.py交给html文件page_form进行渲染展示,同时进行form表单的验证
图:page_form.html+展实效果
2.2.图片上传
图片上传主要有两种方式实现
- 方式一:不使用wtf实现
- 方式二:使用wtf的FileField并添加类型验证
图片上传:不使用wtf
- 1)设置<form>的enctype, enctype="multipart/form-data"
- 2)在视图函数中获取文件对象 request.files
- 3)保存文件 f.save(file_path)
文件名称格式化: werkzeug.utils.secure_filename
示例:
上传不规则的文件名,secure_filename进行格式化
app.py
- 1 import os
- 2
- 3 from flask import Flask, render_template, redirect, url_for, request
- 4 from werkzeug.utils import secure_filename
- 5
- 6 from forms import UserAvatarForm
- 7
- 8 app = Flask(__name__)
- 9 app.config['WTF_CSRF_SECRET_KEY'] = 'abc1234abc'
- 10 app.config['SECRET_KEY'] = 'abc'
- 11 # 自定义的配置扩展,表示文件上传的路径
- 12 app.config['UPLOAD_PATH'] = os.path.join(os.path.dirname(__file__), 'medias')
- 13
- 14 @app.route('/img/upload', methods=['GET', 'POST'])
- 15 def img_upload():
- 16 """ 不使用wtf实现的文件上传 """
- 17 if request.method == 'POST':
- 18 # 获取文件列表
- 19 files = request.files
- 20 file1 = files.get('file1', None)
- 21 if file1:
- 22 # 保存文件
- 23 f_name = secure_filename(file1.filename)
- 24 print('filename:', f_name)
- 25 file_name = os.path.join(app.config['UPLOAD_PATH'], f_name)
- 26 file1.save(file_name)
- 27 print('保存成功')
- 28 return redirect(url_for('img_upload'))
- 29 return render_template('img_upload.html')
img_upload.html
- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>文件上传</title>
- 6 </head>
- 7 <body>
- 8 <form action="/img/upload" method="post" enctype="multipart/form-data">
- 9 <p>
- 10 <input type="file" name="file1">
- 11 <input type="file" name="file2">
- 12 </p>
- 13 <p>
- 14 <input type="submit" value="开始上传">
- 15 </p>
- 16 </form>
- 17 </body>
- 18 </html>
图片上传:验证
- 文件必须上传: FileRequired
- 文件类型验证: FileAllowed
app.py
- 1 import os
- 2
- 3 from flask import Flask, render_template, redirect
- 4 from werkzeug.utils import secure_filename
- 5
- 6 from forms import UserAvatarForm
- 7
- 8 app = Flask(__name__)
- 9 app.config['WTF_CSRF_SECRET_KEY'] = 'abc1234abc'
- 10 app.config['SECRET_KEY'] = 'abc'
- 11 # 自定义的配置扩展,表示文件上传的路径
- 12 app.config['UPLOAD_PATH'] = os.path.join(os.path.dirname(__file__), 'medias')
- 13
- 14
- 15 @app.route('/avatar/upload', methods=['GET', 'POST'])
- 16 def avatar_upload():
- 17 """ 头像上传 """
- 18 form = UserAvatarForm()
- 19 if form.validate_on_submit():
- 20 # 获取图片对象
- 21 img = form.avatar.data
- 22 f_name = secure_filename(img.filename)
- 23 file_name = os.path.join(app.config['UPLOAD_PATH'], f_name)
- 24 img.save(file_name)
- 25 print('保存成功')
- 26 return redirect('/')
- 27 else:
- 28 print(form.errors)
- 29 return render_template('avatar_upload.html', form=form)
forms.py
- 1 from flask_wtf import FlaskForm
- 2 from flask_wtf.file import FileRequired, FileAllowed
- 3 from wtforms import FileField
- 4
- 5
- 6 class UserAvatarForm(FlaskForm):
- 7 """ 用户头像上传 """
- 8 avatar = FileField(label='上传头像', validators=[
- 9 FileRequired('请选择头像文件'),
- 10 FileAllowed(['png'], '仅支持PNG图片上传')
- 11 ])
avatar_upload.html
- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>WTF 文件上传</title>
- 6 </head>
- 7 <body>
- 8 <form action="/avatar/upload" method="post" enctype="multipart/form-data">
- 9 {{ form.csrf_token }}
- 10 <p>
- 11 {{ form.avatar.label }}
- 12 {{ form.avatar }}
- 13 </p>
- 14 <p>
- 15 <input type="submit" value="开始上传">
- 16 </p>
- 17 </form>
- 18 </body>
使用拓展:Flask-Uploads
- 常用文件类型验证
- 指定文件上传的目录
Python全栈工程师之从网页搭建入门到Flask全栈项目实战(6) - Flask表单的实现的更多相关文章
- Python全栈工程师之从网页搭建入门到Flask全栈项目实战(3) - 入门Flask微框架
1.安装Flask 方式一:使用pip命令安装 pip install flask 方式二:源码安装 python setup.py install 验证 第一个Flask程序 程序解释 参数__na ...
- Python全栈工程师之从网页搭建入门到Flask全栈项目实战(1) - ES6标准入门和Flex布局
1.简述 1.什么是ES6?ES6, 全称 ECMAScript 6.0,是 JavaScript 的下一个版本标准,2015年6月份发版.ES6的主要目的是为了解决 ES5 的先天不足. 2.了解E ...
- Web全栈工程师修养
全栈工程师现在是个很热的话题,如何定义全栈工程师?在著名的问答网站Quora上有人提出了这个问题,其中一个获得了高票的回答是: 全栈工程师是指,一个能处理数据库.服务器.系统工程和客户端的所有工作的工 ...
- 阿里巴巴年薪800k大数据全栈工程师成长记
大数据全栈工程师一词,最早出现于Facebook工程师Calos Bueno的一篇文章 - Full Stack (需fanqiang).他把全栈工程师定义为对性能影响有着深入理解的技术通才.自那以后 ...
- 从零开始的全栈工程师——js篇2.8
DOM(document object model) DOM主要研究htmll中的节点(也就是标签) 对节点进行操作 可以改变标签 改变标签属性 改变css样式 添加事件 一.操作流程 1 ...
- EasyNVR无插件播放HLS/RTMP网页直播方案前端完善:监听表单变动
在上一篇博客中我们表述完了防止提交成功后多余操作提交的一个过程:其中的精髓在于ajax的触发事件的使用. 而这篇博客主要想说明一下如何实时的判断出表单是否发生变化. 问题表述: 在网页前端的开发过程中 ...
- Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- EFCodeFirst快速搭建入门
EFCodeFirst快速搭建入门 1.新建Model类库项目. 添加EntityFramework.dll的引用. 编写实体类Course,Student. namespace EFCodeFirs ...
- 测开之Python自动化全栈工程师+性能专项(送思维导图)
测开之Python自动化全栈工程师+性能专项 功能测试基础 接口测试基础接口的通信原理与本质cookie.session.token详解接口测试的意义与测试方法接口测试用例的设计 app测试 app流 ...
- Python全栈工程师(装饰器、模块)
ParisGabriel 每天坚持手写 一天一篇 决定坚持几年 全栈工程师 Python人工智能从入门到精通 装饰器 decorators(专业提高篇) 装饰 ...
随机推荐
- host主机监控规则
1.先在 Prometheus 主程序目录下创建rules目录,然后在该目录下创建 host.yml文件,内容如下: 内容很多,可以根据实际情况进行调整. 规则参考网址:https://awesome ...
- Handler机制与生产者消费者模式
本文梳理了 Handler 的源码,并详细阐述了 Handler 与生产者消费者模式的关系,最后给出了多版自定义 Handler 实现.本文首发于简书,重新整理发布. 一.Handler Handle ...
- 知识图谱实体对齐1:基于平移(translation)的方法
1 导引 在知识图谱领域,最重要的任务之一就是实体对齐 [1](entity alignment, EA).实体对齐旨在从不同的知识图谱中识别出表示同一个现实对象的实体.如下图所示,知识图谱\(\ma ...
- 某云负载均衡获取客户端真实IP的问题
某云负载均衡真实IP的问题,我们这边已经遇到过两次了.而且每次和售后沟通的时候都大费周折,主要是要给售后说明白目前文档的获取真实IP是有问题的,他们觉得文档上说明的肯定没问题,售后要是不明白,他们不会 ...
- sql 中HAVING函数
select * from <表名> group by<过滤的数据> having <晒选的列名>=<条件> 例 select * from villa ...
- PHP全栈开发:在本机上创建虚拟主机与域名
如何在windows+wamp环境上进行自己创建的网站的域名访问 step 1 在wamp的安装目录,如C:\wamp64\www\下创建自己的网站目录pe step 2 右键wamp图标,在wamp ...
- Vue3 Vite3 状态管理 pinia 基本使用、持久化、在路由守卫中的使用
在<基于 vite 创建 vue3 项目>一文中整合了 pinia,有不少伙伴不知道 pinia 是什么,本文简单介绍 pinia.主要包括三方面: pinia 的基本用法,在<基于 ...
- Docker | Compose创建mysql容器
本文通过Docker Compose来创建mysql容器 在linux服务器上创建文件,用于管理容器 mkdir docker-mysql cd docker-mysql vim docker-com ...
- Python编程之子进程管理(subprocess)详解
引言 在写程序时,我们无法避免需要运行外部程序,相较于功能比较简单的os.system(),更加倾向于使用subprocess模块来执行外部程序. 模块介绍 subprocess.run() 使用su ...
- 使用 Kubeadm 部署 K8S安装
1. 安装要求 在开始之前,部署Kubernetes集群机器需要满足以下几个条件: 一台或多台机器,操作系统 CentOS7.x-86_x64 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬 ...