day105:Mofang:设置页面初始化&更新头像/上传头像&设置页面显示用户基本信息
目录
2.setting.js提供avatar_url头像访问地址
1.设置页面初始化
1.设置页面setting.html初始化
APP项目中对于用户的退出登录,一般都在设置中进行。
客户端新增配置页面setting.html
,代码:


<!DOCTYPE html>
<html>
<head>
<title>用户中心</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app user setting" id="app">
<div class="bg">
<img src="../static/images/form_bg.png">
</div>
<!-- 1.设置页面的返回按钮 -->
<img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
<div class="form">
<div class="item avatar">
<span class="title">头像</span>
<span class="goto">></span>
<span class="value">
<img src="../static/images/avatar.png" alt="">
</span>
</div>
<div class="item">
<span class="title">昵称</span>
<span class="goto">></span>
<span class="value">iR.Poke</span>
</div>
<div class="item">
<span class="title">手机号</span>
<span class="goto">></span>
<span class="value">134****9284</span>
</div>
<div class="item">
<span class="title">登陆密码</span>
<span class="value"></span>
<span class="goto">></span>
</div>
<div class="item">
<span class="title">交易密码</span>
<span class="value"></span>
<span class="goto">></span>
</div>
<div class="item">
<span class="title">地址管理</span>
<span class="value"></span>
<span class="goto">></span>
</div>
<div class="item">
<span class="title">设备管理</span>
<span class="value"></span>
<span class="goto">></span>
</div>
<div class="item logout">
<!-- 2.设置页面的切换账号 -->
<img @click="change_account" src="../static/images/change_account.png" alt="">
<!--3.设置页面的退出账号 -->
<p @click="logout">退出账号</p>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
prev:{name:"",url:"",params:{}},
current:{name:"setting",url:"setting.html",params:{}},
}
},
methods:{
goto_home(){
// 回到个人中心界面
this.game.goFrame("user","user.html",this.current);
},
change_account(){
// 切换账号
this.game.goFrame("login","login.html", this.current);
},
logout(){
// 退出账号
api.actionSheet({
title: '您确认要退出当前登录吗?',
cancelTitle: '取消',
destructiveTitle: '退出登录'
}, (ret, err)=>{
if( ret ){
this.game.print(ret);
if(ret.buttonIndex==1){
this.game.save({"access_token":"","refresh_token":""});
this.game.fremove(["access_token","refresh_token"]);
this.game.outWin("user");
}
}
}); }
}
});
}
</script>
</body>
</html>
设置页面setting.html初始化
2.设置页面的CSS样式
static/css/main.css
,样式代码:


.setting .bg img{
animation: normal;
}
.setting .back{
top: 4rem;
}
.setting .form {
top: 9rem;
}
.setting .form .item{
height: 3.9rem;
line-height: 3.9rem;
font-size: 1.25rem;
text-indent: 0.6rem;
border-bottom: 1px solid rgba(204,153,102,0.2);
}
.setting .form .avatar{
height: 6.11rem;
line-height: 6.11rem;
}
.setting .form .avatar img{
width: 4.56rem;
height: 4.56rem;
vertical-align: middle;
}
.setting .form .item .value,
.setting .form .item .goto{
float: right;
}
.setting .form .logout{
margin-top: 3rem;
text-align: center;
height: 4rem;
line-height: 2rem;
}
.setting .form .logout img{
width: 11rem;
}
设置页面的CSS样式
3.用户界面点击设置按钮跳转到设置界面
<!-- 点击设置按钮去到设置界面 -->
<img class="setting" @click="goto_setting" src="../static/images/setting.png" alt=""> <script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
prev:{name:"",url:"",params:{}},
current:{name:"user",url:"user.html",params:{}},
}
},
methods:{
goto_setting(){
this.game.goFrame("setting","setting.html", this.current);
}
}
});
}
</script>
</body>
</html>
2.更新头像
1.点击头像进入更新头像界面
点击头像进入更新头像页面,setting.html
,代码:
<span class="value">
<!-- 点击头像进入到更新头像界面 -->
<img @click="update_avatar_frame" src="../static/images/avatar.png" alt="">
</span> <script> update_avatar_frame(){
// 点击头像,跳到更新头像的界面:avatar.html
this.game.goFrame("avatar","avatar.html", this.current,null,{
type:"push", //动画类型(详见动画类型常量)
subType:"from_top", //动画子类型(详见动画子类型常量)
duration:300 //动画过渡时间,默认300毫秒
})
} </script>
2.更新头像页面初始化
avatar.html
,显示页面,代码:


<!DOCTYPE html>
<html>
<head>
<title>用户中心</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar" id="app">
<div class="box">
<p class="title">上传头像</p>
<img class="close" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
prev:{name:"",url:"",params:{}},
current:{name:"avatar",url:"avatar.html",params:{}},
}
},
methods:{
update_avatar_confirm(){
// 确认上传头像 },
upload_avatar(ret){
// 头像上传处理 }
}
});
}
</script>
</body>
</html>
更新头像页面avatar.html初始化
3.更新头像页面CSS样式
main.css
,页面样式,代码:


.avatar.frame{
background-color: rgba(0,0,0,0.6);
}
.avatar{
overflow: hidden;
}
.avatar .box{
width: 28.89rem;
height: 34.44rem;
background: url("../images/board_bg1.png") no-repeat 0 0;
background-size: 100%;
position: absolute;
top: 11rem;
margin: 0 auto;
left: 0;
right: 0;
} .avatar .box .title{
color: #fff;
font-size: 2rem;
text-align: center;
margin-top: 2.8rem;
}
.avatar .box .close{
width: 5.22rem;
height: 5.78rem;
position: absolute;
right: 0;
top: 8rem;
}
.avatar .box .header{
margin-top: 3.6rem;
font-size: 1.8rem;
text-align: center;
color: #ff3333;
font-weight: bold;
}
.avatar .box .text{
width: 16.67rem;
margin: 1.4rem auto 0;
font-size: 1.22rem;
color: #ffffcc;
}
.avatar .box .btn{
display: block;
width: 12.22rem;
height: 4.55rem;
margin: 1.4rem auto 0;
}
更新头像页面CSS样式
4.头像上传来源选择:相册/相机
头像上传来源选择,avatar.html
,代码:
<!-- 1.关闭更新头像界面: close_frame -->
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<!-- 2.头像上传来源选择 :相册/相机 -->
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div> <script> close_frame(){
this.game.outFrame("avatar");
}, update_avatar_confirm(){
// 确认上传头像的方式
api.actionSheet({
title: '请选择上传头像的来源',
cancelTitle: '取消',
buttons: ['相册','相机'],
}, function(ret, err){
if( ret ){
alert( JSON.stringify( ret ) );
}else{
this.game.print( err );
}
}); }, </script>
5.调用api提供的本地接口从相册/相机提取图片
接下来,调用apicloud
提供的本地接口从相册或者相机中提取图片.
avatar.html
代码
<!-- 1.关闭更新头像界面: close_frame -->
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<!-- 2.头像上传来源选择 :相册/相机 -->
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div>
<script> close_frame(){
this.game.outFrame("avatar");
},
update_avatar_confirm(){
// 确认上传头像的方式
api.actionSheet({
title: '请选择上传头像的来源',
cancelTitle: '取消',
buttons: ['相册','相机'],
}, (ret, err)=>{
if( ret ){
var sourceType = ["album","camera"];
if(ret.buttonIndex > sourceType.length){
// 如果用户选择了取消,则关闭当前修改头像的页面
this.game.outFrame("avatar");
return;
}
// ***使用APIcloud提供的api.getPicture方法从相机/相册获取图片***
api.getPicture({
sourceType: sourceType[ret.buttonIndex-1],
mediaValue: 'pic',
destinationType: 'base64',
allowEdit: true,
preview:true,
quality: 50,
targetWidth: 100,
targetHeight: 100,
saveToPhotoAlbum: true,
}, (ret, err)=>{
if(ret){
this.game.print(ret);
}else{
this.game.print(err);
}
}); alert( JSON.stringify( ret ) );
}else{
this.game.print( err );
}
}); },
upload_avatar(ret){
// 头像上传处理 }
}
});
}
</script>
</body>
</html>
6.后端提供头像更新的接口
服务端提供头像更新接口,application/apps/users/views.py
,代码
import base64, uuid,os
@jsonrpc.method("User.avatar.update")
@jwt_required # 验证jwt
def update_avatar(avatar):
"""获取用户信息"""
# 1.接受客户端上传的头像信息
ext = avatar[avatar.find("/")+1:avatar.find(";")] # 资源格式:jpeg/jpg/png....
b64_avatar = avatar[avatar.find(",")+1:]
b64_image = base64.b64decode(b64_avatar) # 2.使用uuid给头像文件生成随机的文件名
filename = uuid.uuid4() # 3.拼接头像文件在后端存储的路径
static_path = os.path.join( current_app.BASE_DIR,current_app.config["STATIC_DIR"] )
with open("%s/%s.%s" % (static_path, filename,ext),"wb") as f:
f.write(b64_image) # 4.查询当前用户是否存在
current_user_id = get_jwt_identity()
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
} # 5.将用户的头像数据存储到mysql数据库中
user.avatar = "%s.%s" % (filename,ext)
db.session.commit()
return {
"errno": status.CODE_OK,
"errmsg": message.avatar_save_success,
"avatar": "%s.%s" % (filename,ext)
}
在项目后端全局配置文件中添加静态文件目录存储路径
application/settings/__init__.py
,代码:
# 静态文件目录存储路径
STATIC_DIR = "application/static"
7.前端基于axios上传图片数据
客户端基于axios上传图片数据,avatar.html
代码
<!-- 1.关闭更新头像界面: close_frame -->
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="content">
<p class="header">!注意事项</p>
<p class="text">禁止使用有诱导性的内容,二维码,联系方式等违规违法违约的图片,一经发现,永久封号,
并保留追究法律责任的权利。</p>
</div>
<!-- 2.头像上传来源选择 :相册/相机 -->
<img @click="update_avatar_confirm" class="btn" src="../static/images/yes.png" alt="">
</div>
<script> close_frame(){
this.game.outFrame("avatar");
},
update_avatar_confirm(){
api.actionSheet({
title: '请选择上传头像的来源',
cancelTitle: '取消',
buttons: ['相册','相机'],
}, (ret, err)=>{
if( ret ){
var sourceType = ["album","camera"];
if(ret.buttonIndex > sourceType.length){
this.game.outFrame("avatar");
return;
}
api.getPicture({
...
}, (ret, err)=>{
if(ret){
// 1.获取本地图片成功后,开始上传图片
this.upload_avatar(ret);
}else{
this.game.print(err);
}
}); }else{
this.game.print( err );
}
}); },
// 头像上传处理
upload_avatar(ret){ var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
// 2.前端基于axios上传头像
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.avatar.update",
"params": {
"avatar": ret.base64Data,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.game.print(response);
}else{
this.game.print(response.data.result);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
})
}
}
});
}
</script>
</body>
</html>
3.本地更新头像信息
1.头像上传成功后-关闭页面/将头像数据存储在前端
关闭avatar.html
页面,展示底下的setting.html
,并将头像存储在前端
客户端的avatar.html
代码:
upload_avatar(ret){
// 头像上传处理
var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.avatar.update",
"params": {
"avatar": ret.base64Data,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
// 当后端存储头像数据成功后
if(parseInt(response.data.result.errno)==1000){
// 1.将头像存储在前端
this.game.fsave({"avatar": response.data.result.avatar});
// 2.跳转到设置页面
this.game.goFrame("setting","setting.html", this.current);
}else{
this.game.print(">>>> fail");
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
})
}
}
});
}
2.setting.js提供avatar_url头像访问地址
客户端的配置文件static/js/settings.js
新增配置项avatar_url提供头像访问地址,代码;
function init(){
if(Game){
var game = new Game("../mp3/bg1.mp3");
Vue.prototype.game = game;
}
if(axios){
// 初始化axios
axios.defaults.baseURL = "http://192.168.20.251:5000/api" // 服务端api接口网关地址
axios.defaults.timeout = 2500; // 请求超时时间
axios.defaults.withCredentials = false; // 跨域请求资源的情况下,忽略cookie的发送
Vue.prototype.axios = axios;
Vue.prototype.uuid = UUID.generate;
}
// 接口相关的配置项
Vue.prototype.settings = {
captcha_app_id: "2071340228", // 腾讯防水墙验证码应用ID
avatar_url: "http://192.168.20.251:5000/users/avatar", // ***头像前端访问地址***
}
}
3.后端提供展示头像的视图方法
服务端提供展示头像的视图方法地址
application/apps/users/urls.py
,代码:
from . import views
from application.utils import path
urlpatterns = [
path("/avatar", views.avatar),
]
确认总路由设置了访问蓝图的url前缀,application/urls.py
,代码:
from application.utils import include
urlpatterns = [
include("","home.urls"),
include("/users","users.urls"),
include("/marsh","marsh.urls"),
]
视图中, 显示图片时验证用户身份.,application/apps/users/views.py
代码:
from flask import make_response,request
@jwt_required # 验证jwt
def avatar():
"""获取头像信息""" # 1.获取前端存储头像的sign参数
avatar = request.args.get("sign") # 2.获取头像文件格式:jpg/jpeg/png
ext = avatar[avatar.find(".")+1:] # 3.获取头像文件的文件名
filename = avatar[:avatar.find(".")] # 4.后端文件存储的路径
static_path = os.path.join(current_app.BASE_DIR, current_app.config["STATIC_DIR"]) # 5.读取后端文件数据
with open("%s/%s.%s" % (static_path,filename,ext), "rb") as f:
content = f.read() # 此时content存储的是二进制文件
response = make_response(content) #
response.headers["Content-Type"] = "image/%s" % ext
return response
4.设置页面头像立即刷新
完成了上面步骤代码以后, 我们现在能在客户端修改用户头像了,但是在关闭avatar.html页面以后, setting.html页面中的头像并没有及时发生变化,.所以我们在avatar.html页面更新了头像以后, 我们借住apicloud
提供的自定义事件和事件监听接口,来实现,通知setting.html页面,用户头衔已经发生改变了.
文档: https://docs.apicloud.com/Client-API/api#72
当前功能,我们需要根据文档了解关于sendEvent
和addEventListener
的使用.
// a页面可以通过sendEvent发起一个自定义事件
api.sendEvent({
name: 'myEvent', # 自定义事件名称
extra: {
key1: 'value1', # 事件传参
key2: 'value2'
}
}); // b页面可以通过addEventListener进行监听是否有对应名称的自定义事件进行发送了,一旦监听到,则自动执行回调函数:
api.addEventListener({
name: 'myEvent' # 监听指定名称的事件
}, function(ret, err) { # ret接收指定名称的事件参数
alert(JSON.stringify(ret.value));
}); // c页面也可以通过addEventListener进行监听是否有对应名称的自定义事件进行发送了,一旦监听到,则自动执行回调函数:
api.addEventListener({
name: 'myEvent'
}, function(ret, err) {
alert(JSON.stringify(ret.value));
}); // b.c 页面都将收到 myEvent 事件
1.avatar.html发送自定义事件
接下来,我们就可以在avatar.html
页面中,发送一个自定义事件,告知其他页面,当前用户的头像发生了改变.
avatar.html
代码
upload_avatar(ret){
// 头像上传处理
var token = this.game.get("access_token") || this.game.fget("access_token");
if(!token){
this.game.goFrame("login","login.html", this.current);
return ;
}
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.avatar.update",
"params": {
"avatar": ret.base64Data,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.game.fsave({"avatar": response.data.result.avatar});
// ***发送自定义事件***
api.sendEvent({
name: 'change_avatar',
extra: {
"avatar": response.data.result.avatar
}
});
this.game.outFrame("avatar");
}else{
this.game.print(">>>> fail");
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
})
}
}
});
}
2.setting.html监听自定义事件
在setting.html
页面中,监听自定义事件,这个监听过程是不需要刷新页面的.
methods:{
change_avatar(){
// 监听自定义事件
api.addEventListener({
name: 'change_avatar'
}, (ret, err)=>{
if( ret ){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.avatar = `${this.settings.avatar_url}?sign=${ret.value.avatar}&token=${token}`;
}
});
},
5.前端页面显示当前登录用户的基本信息
setting.html
页面提供当前登陆用户的基本信息,代码:
</div>
<div class="item">
<span class="title">昵称</span>
<span class="goto">></span>
<span class="value">{{nickname}}</span>
</div>
<div class="item">
<span class="title">手机号</span>
<span class="goto">></span>
<span class="value">{{mobile}}</span>
</div> <script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
nickname: "", // 昵称
mobile: "", // 手机号
avatar: "../static/images/avatar.png",
prev:{name:"",url:"",params:{}},
current:{name:"setting",url:"setting.html",params:{}},
}
},
created(){
this.get_user_info(); // 触发获取用户信息方法
this.change_avatar();
},
methods:{
// 获取当前用户登录基本信息
get_user_info(){
var token = this.game.get("access_token") || this.game.fget("access_token");
// 获取当前登陆用户基本信息
this.axios.post("",{
"jsonrpc": "2.0",
"id": this.uuid(),
"method": "User.info",
"params": {}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
var res = response.data.result;
if(parseInt(res.errno) === 1000){
this.nickname = res.nickname;
// avatar从前端获取传到:src上
this.avatar = `${this.settings.avatar_url}?sign=${res.avatar}&token=${token}`;
this.mobile = res.mobile;
}
})
}, </script>
</body>
</html>
6.后端提供用户基本信息的API接口
服务端提供用户基本信息APi接口,application/apps/users/views.py
,代码:
from .marshmallow import UserInfoSchema
@jsonrpc.method("User.info")
@jwt_required # 验证jwt
def info():
"""获取用户信息"""
current_user_id = get_jwt_identity() # 根据token反解出当前用户id # 判断当前用户是否存在
user = User.query.get(current_user_id)
if user is None:
return {
"errno": status.CODE_NO_USER,
"errmsg": message.user_not_exists,
}
uis = UserInfoSchema()
data = uis.dump(user) # 将用户信息序列化传递给前端
return {
"errno": status.CODE_OK,
"errmsg": message.ok,
**data
}
marshmallow.py
,代码:
from marshmallow import post_dump
class UserInfoSchema(SQLAlchemyAutoSchema):
id = auto_field()
mobile = auto_field()
nickname = auto_field()
avatar = auto_field() class Meta:
model = User
include_fk = True
include_relationships = True
fields = ["id","mobile","nickname","avatar"]
sql_session = db.session @post_dump()
def mobile_format(self, data, **kwargs):
data["mobile"] = data["mobile"][:3]+"****"+data["mobile"][-4:]
return data
day105:Mofang:设置页面初始化&更新头像/上传头像&设置页面显示用户基本信息的更多相关文章
- php头像上传预览
php头像上传带预览: 说道上传图片,大家并不陌生,不过,在以后开发的项目中,可能并不会让你使用提交刷新页面式的上传图片,比如上传头像,按照常理,肯定是在相册选择照片之后,确认上传,而肯定不会通过fo ...
- Django 自带 user 字段扩展及头像上传
django 及 rest_framework 笔记链接如下: django 入门笔记:环境及项目搭建 django 入门笔记:数据模型 django 入门笔记:视图及模版 django 入门笔记:A ...
- spring--mvc添加用户及用户头像上传
spring--mvc添加用户及用户头像上传 添加用户步骤: 1.用ajax获取省份信息 2.添加用户 代码:register.jsp <meta http-equiv="Conten ...
- Django实现注册页面_头像上传
Django实现注册页面_头像上传 Django实现注册页面_头像上传 1.urls.py 配置路由 from django.conf.urls import url from django.cont ...
- vue中使用axios post上传头像/图片并实时显示到页面
在前端开发中,为了更好的用户体验,在头像上传时会先将图片显示到页面然后点击保存按钮 完成图片的上传成功 代码部分有参考他人的写法. html代码: <div id="myPhoto ...
- 强大的flash头像上传插件(支持旋转、拖拽、剪裁、生成缩略图等)
今天介绍的这款flash上传头像功能非常强大,支持php,asp,jsp,asp.net 调用 头像剪裁,预览组件插件. 本组件需要安装Flash Player后才可使用,请从http://dl.pc ...
- 【Bootstrap-插件使用】Jcrop+fileinput组合实现头像上传功能
作者:Dreawer链接:https://zhuanlan.zhihu.com/p/24465742来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:梦游的龙猫(转 ...
- [Bootstrap-插件使用]Jcrop+fileinput组合实现头像上传功能
很久没有更新博客了,再不写点东西都烂了. 这次更新一个小内容,是两个插件的组合使用,实现头像上传功能. 业务需求: 头像上传功能,要对上传的文件进行剪切,且保证头像到服务器时必须是正方形的. 优化&l ...
- python 全栈开发,Day86(上传文件,上传头像,CBV,python读写Excel,虚拟环境virtualenv)
一.上传文件 上传一个图片 使用input type="file",来上传一个文件.注意:form表单必须添加属性enctype="multipart/form-data ...
随机推荐
- Serilog 源码解析——数据的保存(上)
在上一篇中,我们主要研究了Serilog是如何解析字符串模板的,它只是单独对字符串模板的处理,对于日志记录时所附带的数据没有做任何的操作.在本篇中,我们着重研究日志数据的存储方式.(系列目录) 本篇所 ...
- innodb为什么需要doublewrite(转)
InnoDB的page size默认是16KB,而操作系统的一个block size是4KB,磁盘io block则更小.那么InnoDB的page刷到磁盘上要写4个操作系统block,在极端情况下( ...
- 运维和shell
什么是运维 术语名词 IDC--(Internet Data Center)互联网数据中心,主要服务包括整机租用.服务器托管.机柜租用.机房租用.专线接入和网络管理服务等.广义上的IDC业务,实际上就 ...
- MTK官方SDK包编译openwrt
全过程需要联网,最好有梯子,编译方式有两种 安装依赖库: apt-get install g++ apt-get install libncurses5-dev apt-get install zli ...
- 熬夜肝出5大点,18张图带你彻底弄懂MySQL事务日志
在当今社会,充斥着大量的数据.从众多APP上的账户资料到银行信用体系等个人档案,都离不开对大量数据的组织.存储和管理.而这,便是数据库存在的目的和价值.目前数据库的类型主要分为两种,一种是关系型数据库 ...
- Flink处理函数实战之一:深入了解ProcessFunction的状态(Flink-1.10)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Microsoft Visual C++ 2005 SP1无法安装
安装时出现需要Microsoft Visual C++ 2005 Redistributble对话框, 里面说Command line option syntax error . Type Comma ...
- kettle——转换案例
把stu1的数据按id同步到stu2,stu2有相同id则更新数据 (1)在mysql中创建两张表 mysql> create database kettle; mysql> use ke ...
- Mysql数据安全备份
数据安全备份的意义 在出现意外的时候(硬盘损坏.断点.黑客攻击),以便数据的恢复 导出生产的数据以便研发人员或者测试人员测试学习 高权限的人员那操作失误导致数据丢失,以便恢复 备份类型 完全备份:对整 ...
- 面试官:小伙子,给我说一下mysql 乐观锁和悲观锁吧
悲观锁介绍 悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中, 将数据处于锁定状态.悲观锁的实现,往往依靠数据库 ...