1209 BBS 登录
上周内容
bbs项目
项目开发流程
需求分析
架构设计
分组开发
我们一般情况下都只是作用于这一步
各项测试
交付上线
bbs表设计
任何一个项目 最最重要的部分都是数据库的表设计
用户表
继承AbstractUser表 来做额外的字段扩展
1.类的继承
2.配置文件配置
AUTH_USER_MODEL = '应用名.类名'
phone
avatar
upload_to='avatar/'
register_time
个人站点表
站点标题
站点名称
站点样式
模拟
文章标签表
标签名称
文章分类表
分类名称
文章表
文章标题
文章简介
文章内容
文章日期
# 数据库优化字段
点赞数
点踩数
评论数
点赞点踩表
用户id 一对多字段
文章id 一对多字段
点赞点踩 1/0
评论表
用户id 一对多字段
文章id 一对多字段
评论内容
评论时间
自关联字段 自己跟自己所在的表关联
数据库配置
1.配置文件
2.__init__文件
数据库迁移命令
python3 manage.py makemigrations
python3 manage.py migrate
注册功能
只要是注册功能一般都有一定的校验规则
我们利用forms组件 来完成注册的校验
用户名
label
error_messages
required
invalid
widget
validators
密码
确认密码
邮箱
钩子函数
校验用户名是否已存在
校验两次密码是否一致
一旦你的项目特别庞大 需要用到很多forms组件
那么你可以单独的将所有forms组件放到一个py文件中或者一个文件下
然后针对不同的功能开设不同的py文件
单独的py文件
文件夹
1.py
2.py
3.py
4.py
注册功能使用的是ajax做后端交互
但是我们用的了form标签
因为form标签有一个自动序列化普通键值对的功能
可以方便的将普通键值对循环添加到formdata对象中
label标签在跟input有绑定关系的前提下
内部无论放什么对象 点击都能够是对应的input框聚焦
img标签src属性可以放的值
1.图片的地址
2.图片的二进制数据
3.后端url 自动朝该url发送get请求
实时展示用户选择的头像
利用内置对象fileReader
文件阅读器在读取文件的时候 是一个异步io操作
所以你在渲染img标签的时候一定要等待文件阅读器加载完毕之后再渲染
等待...加载完毕
onload
window.onload = function(){}
fileReader.onload = function(){}
发送ajax请求
1.ajax提交数据基本语法
2.ajax发送文件需要借助于内置对象formdata
ajax发送formdata对象
需要制定两个参数都为false
processData
contentType
后端正常的业务逻辑无需多说
一旦报错之后前端如何对应的渲染相应的信息
1.你需要研究form组件渲染的input框的id值的特点
id_字段名
2.你又发现返回的报错信息 键就是一个个的字段名
自己手动拼接处input框的id值
然后利用DOM操作 来操作span标签以及div标签
最后为了功能的健壮性
给所有的input设置获取焦点事件
自动移除报错信息和报错的样式
控制字体样式的文件都是以.ttf结尾
本周
bbs结束
今日内容
登录功能
首页搭建
导航条用户功能
admin后台管理
下周安排(15d~22d)
vue前端框架 3~5d
django restframework(******)
路飞项目
git
celery
项目上线
今日内容
url.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 注册功能
url(r'^register/',views.register,name='register'),
# 登录功能
url(r'^login/',views.login,name='login'),
# 验证码图片
url(r'^get_code/',views.get_code,name='code'),
# 首页搭建
url(r'^home/',views.home,name='home'),
# 退出登录
url(r'^logout/',views.logout,name='logout'),
# 修改密码
url(r'^set_password/',views.set_password,name='set_pwd')
]
views.py
from django.shortcuts import render,HttpResponse,redirect,reverse
from app01 import myform
from app01 import models
from django.http import JsonResponse
# 验证码相关
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO, StringIO
# auth模块校验密码
from django.contrib import auth
from django.contrib.auth.decorators import login_required
# Create your views here.
def register(request):
# 生成一个空的forms对象
form_obj = myform.MyRegForm()
if request.method == 'POST':
back_dic = {'code':1000,'msg':''}
# 对用户提交的数据先进行校验 forms
# 直接使用forms组件的校验方法,校验整个的数据字典
form_obj = myform.MyRegForm(request.POST)
if form_obj.is_valid():
# 如果数据校验结果正确
clean_data = form_obj.cleaned_data # 获取正确的数据 4个键值对
# 将确认密码的键值对弹出,只剩余三个便于创建用户
clean_data.pop('confirm_password')
# 获取用户上传的文件
file_obj = request.FILES.get('avatar')
# 判断文件是否存在,用户是否上传,如果没有上传才会设置default头像
if file_obj:
clean_data['avatar'] = file_obj # 四个键值对
# 自动创建,使用**直接打散关键字参数
models.Userinfo.objects.create_user(**clean_data)
# 添加成功界面信息,及跳转
back_dic['msg'] = '注册成功'
back_dic['url'] = '/login/'
else:
back_dic['code'] = 2000
# 将错误信息返回给前端
back_dic['msg'] = form_obj.errors
# 返回给前端字典
return JsonResponse(back_dic)
return render(request,'register.html',locals())
# 登录功能
def login(request):
if request.method == 'POST':
back_dic = {'code':1000,'msg':''}
username = request.POST.get('username')
password = request.POST.get('password')
code = request.POST.get('code')
# 1.先校验验证码是否正确 忽略大小写
if request.session.get('code').upper() == code.upper():
# 2.校验用户名密码是否正确 利用auth模块
user_obj = auth.authenticate(request,username=username,password=password)
if user_obj:
# 3.保存用户登录状态
auth.login(request,user_obj)
# 就可以在任意位置通过request.user获取到当前登录对象 并且 request.user.is_authenticated()判断当前用户是否登录
# 返回前端信息,并定向主页
back_dic['msg'] = '登录成功'
back_dic['url'] = '/home/'
else:
back_dic['code'] = 2000
back_dic['msg'] = '用户名或密码错误'
else:
back_dic['code'] = 3000
back_dic['msg'] = '验证错误'
# 返回给前端字典数据
return JsonResponse(back_dic)
return render(request,'login.html')
import random
# 给验证码的图片添加随机颜色
def get_random():
return random.randint(0,255),random.randint(0,255),random.randint(0,255)
# 图片验证码相关
def get_code(request):
# 推导步骤一:直接发送后端存在的图片
# img标签可以直接返回二进制数据进行显示
# with open(r'static/img/02b02.jpg.jpg','rb') as f:
# data = f.read()
# return HttpResponse(data)
# 推导步骤二 利用pillow模块自动生成图片
'''
from PIL import Image,ImageDraw,ImageFont
Image 生成图片
ImageDraw 在图片上写字
ImageFont 控制字体的样式'''
# 生成图片对象
# img_obj = Image.new('RGB',(360,35),'red') 直接放文件的颜色
# img_obj = Image.new('RGB',(360,35),get_random()) # 放rgb模式(255,23,232)
# # 利用文件操作先保存下来
# with open('xxx.png','wb') as f:
# img_obj.save(f,'png')
# # 然后利用文件操作将图片数据读取并发送
# with open(r'xxx.png','rb') as f:
# data = f.read()
# return HttpResponse(data)
# 推导步骤三 临时存储数据并且能够随时取出的地方
'''内存管理模块
from io import BytesIO,StringIO
BytesIO 保存数据(并且在获取的时候,是以二进制的方式给你)
StringIO 保存数据(以字符串的形式给你)
'''
# img_obj = Image.new('RGB',(360,35),get_random())
# # # 先生成一个io对象
# # io_obj = BytesIO() # 可以将对象当做是文件的句柄
# # # 存储数据
# # img_obj.save(io_obj,'png')
# # # getvalue获取二进制的数据
# # return HttpResponse(io_obj.getvalue())
# 推导步骤四 在图片上写字
img_obj = Image.new('RGB',(360,35),get_random())
# 将生成好的图片对象交给imageDraw
img_draw = ImageDraw.Draw(img_obj) # 生成一个画笔对象
# 字体样式,将ttf格式字体,及字体的大小 设置
img_font = ImageFont.truetype('static/fonts/1.ttf',30)
# 产生一个随机验证码 大小写英文加数字 五位,每一位都可以是大小写数据
code= ''
for i in range(5):
# chr 根据数字对应字符编码的英文
upper_str = chr(random.randint(65,90))
lower_str = chr(random.randint(97,122))
random_int = str(random.randint(0,9))
# 随机选取一个字符
tmp = random.choice([upper_str,random_int,lower_str])
# 向图片中写入一个((x轴,y轴)坐标,文本,图片北京,字体样式)
img_draw.text((i*60+60,0),tmp,get_random(),img_font)
# 存储写的字
code += tmp
print(code)
# 这个验证码后面的其他视图函可能用得上,找到地方保存,并且这个地方的全局视图函数都可以访问
request.session['code'] = code
# 图片保存
io_obj = BytesIO()
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
# 首页的搭建
def home(request):
return render(request,'home.html',locals())
# 退出登录
@login_required
def logout(request):
# 退出登录
auth.logout(request)
# 重定向到主页
return redirect(reverse('home'))
@login_required
def set_password(request):
if request.method == 'POST':
old_pwd = request.POST.get('old_password')
new_pwd = request.POST.get('new_password')
confirm_password = request.POST.get('confirm_password')
# 1.先判断旧密码是否正确
is_right = request.user.check_password(old_pwd)
if is_right:
# 判断新密码与确认密码是否一致
if new_pwd == confirm_password:
# 修改密码
request.user.set_password(new_pwd)
request.user.save()
# 重定向界面
return redirect(reverse('login'))
else:
return HttpResponse('两次密码不一致')
else:
return HttpResponse('原密码不正确')
login
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 ">
<h2 class="text-center">登录界面</h2>
<div class="form-group">
<label for="id_username">用户名</label>
<input type="text" name="username" id="id_username" class="form-control">
</div>
<div class="form-group">
<label for="id_password">密码</label>
<input type="password" name="password" id="id_password" class="form-control">
</div>
{# 验证码框#}
<div class="form-group">
<label for="id_code">验证码</label>
<div class="row">
<div class="col-md-6">
<input type="text" name="code" id="id_code" class="form-control">
</div>
<div class="col-md-6">
<img src="/get_code/" alt="" width="360" height="35" id="id_img">
</div>
</div>
</div>
<input type="button" class="btn btn-primary" value="登录" id="id_submit">
{# // 错误信息的展示#}
<span style="color: red;" id="id_error"></span>
</div>
</div>
</div>
<script>
{#绑定验证码点击刷新事件#}
$('#id_img').click(function () {
var oldPath = $(this).attr('src');
$(this).attr('src',oldPath+='?')
});
{#发送ajax请求与后端交互#}
$('#id_submit').click(function () {
$.ajax({
url:'',
type:'post',
data:{
'username':$('#id_username').val(),
'password':$('#id_password').val(),
'code':$('#id_code').val(),
'csrfmiddlewaretoken':'{{ csrf_token }}'
},
{#进行处理后端数据#}
success:function (data) {
if(data.code==1000){
// 验证成功则跳转主页
window.location.href = data.url
}else { // 报错信息的展示
$('#id_error').text(data.msg)
}
}
})
})
</script>
</body>
</html>
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主页</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
{#导航条样式#}
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/home/">BBS首页系统</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">文章 <span class="sr-only">(current)</span></a></li>
<li><a href="#">随笔</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多 <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
{# 判断用户是否登录 显示登录注册按钮#}
{% if request.user.is_authenticated %}
{# 根据后端,显示登录之后的按钮#}
<li><a href="#">{{ request.user.username }}</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多操作 <span class="caret"></span></a>
<ul class="dropdown-menu">
{# 添加模态框的属性data-toggle="modal" data-target="#myModal"#}
<li><a data-toggle="modal" data-target="#myModal">修改密码</a></li>
<li><a href="#">修改头像</a></li>
<li><a href="#">后台管理</a></li>
<li role="separator" class="divider"></li>
<li><a href="{% url 'logout' %}">退出登录</a></li>
</ul>
</li>
{% else %}
{# 没有登录则显示登录注册按钮#}
<li><a href="{% url 'login' %}">登录</a></li>
<li><a href="{% url 'register' %}">注册</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{#整体页面布局#}
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
{# 左边面板#}
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">点击就送</h3>
</div>
<div class="panel-body">
劳斯莱斯5元代金券
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">限定优惠</h3>
</div>
<div class="panel-body">
割双眼皮买二送一
</div>
</div>
<div class="panel panel-warning">
<div class="panel-heading">
<h3 class="panel-title">最后换购</h3>
</div>
<div class="panel-body">
买电烤炉送蜂窝煤一斤!
</div>
</div>
</div>
{# 中间面板 #}
<div class="col-md-8"></div>
<div class="col-md-2">
{# 右边面板#}
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">点击就送</h3>
</div>
<div class="panel-body">
劳斯莱斯5元代金券
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">限定优惠</h3>
</div>
<div class="panel-body">
割双眼皮买二送一
</div>
</div>
<div class="panel panel-warning">
<div class="panel-heading">
<h3 class="panel-title">最后换购</h3>
</div>
<div class="panel-body">
买电烤炉送蜂窝煤一斤!
</div>
</div>
</div>
</div>
</div>
{#修改密码的弹出框#}
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">修改密码</h4>
</div>
<div class="modal-body">
{# 设置密码的更改#}
<form action="{% url 'set_pwd' %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="id_username">用户名</label>
<input type="text" id="id_username" name="username" disabled class="form-control" value="{{ request.user.username }}">
</div>
<div class="form-group">
<label for="id_password">初始密码</label>
<input type="password" id="id_password" name="old_password" class="form-control" >
</div>
<div class="form-group">
<label for="id_new_password">新密码</label>
<input type="password" id="id_new_password" name="new_password" class="form-control" >
</div>
<div class="form-group">
<label for="id_confirm_password">确认新密码</label>
<input type="password" id="id_confirm_password" name="confirm_password" class="form-control">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button class="btn btn-primary" id="id_s">提交</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
逻辑流程
登录功能
1.定义登录界面
2.添加验证码的功能
图片验证码的传值有三种方式,直接写地址,文件二进制数据,路径
验证码的实现
通过Image获取imgobj对象
生成好的img对象交给ImageDraw.Draw 生成画笔
定义字体样式,文字大小
产生随机的验证码,利用chr实现,(65,96)大写,(97,122)小写,数字直接就是0-9
随机5个数字,在每个循环里写入
利用画笔对象.text((x轴,y轴)坐标,文本,图片北京,字体样式)
存储写的字
保存到session中的code
然后保存图片io
最终返回给前端值 return HttpResponse(io_obj.getvalue())
3.给验证码绑定点击事件
每点击一次url添加一个?用于刷新
4.使用ajax与后端进行交互
将用户的输入获取到手
success回调函数拿到后端返回的数据
根据code的信信息对相关标签进行渲染
后端得到数据进行验证
先判断验证码是否正确
然后利用auth模块判断密码是否正确
根据得到对象判断存在
定义返回字典,返回给前端
return JsonResponse(back_dic)
验证码相关推导
def get_code(request):
# 推导步骤一:直接发送后端存在的图片
# img标签可以直接返回二进制数据进行显示
# with open(r'static/img/02b02.jpg.jpg','rb') as f:
# data = f.read()
# return HttpResponse(data)
# 推导步骤二 利用pillow模块自动生成图片
'''
from PIL import Image,ImageDraw,ImageFont
Image 生成图片
ImageDraw 在图片上写字
ImageFont 控制字体的样式'''
# 生成图片对象
# img_obj = Image.new('RGB',(360,35),'red') 直接放文件的颜色
# img_obj = Image.new('RGB',(360,35),get_random()) # 放rgb模式(255,23,232)
# # 利用文件操作先保存下来
# with open('xxx.png','wb') as f:
# img_obj.save(f,'png')
# # 然后利用文件操作将图片数据读取并发送
# with open(r'xxx.png','rb') as f:
# data = f.read()
# return HttpResponse(data)
# 推导步骤三 临时存储数据并且能够随时取出的地方
'''内存管理模块
from io import BytesIO,StringIO
BytesIO 保存数据(并且在获取的时候,是以二进制的方式给你)
StringIO 保存数据(以字符串的形式给你)
'''
# img_obj = Image.new('RGB',(360,35),get_random())
# # # 先生成一个io对象
# # io_obj = BytesIO() # 可以将对象当做是文件的句柄
# # # 存储数据
# # img_obj.save(io_obj,'png')
# # # getvalue获取二进制的数据
# # return HttpResponse(io_obj.getvalue())
# 推导步骤四 在图片上写字
img_obj = Image.new('RGB',(360,35),get_random())
# 将生成好的图片对象交给imageDraw
img_draw = ImageDraw.Draw(img_obj) # 生成一个画笔对象
# 字体样式,将ttf格式字体,及字体的大小 设置
img_font = ImageFont.truetype('static/fonts/1.ttf',30)
# 产生一个随机验证码 大小写英文加数字 五位,每一位都可以是大小写数据
code= ''
for i in range(5):
# chr 根据数字对应字符编码的英文
upper_str = chr(random.randint(65,90))
lower_str = chr(random.randint(97,122))
random_int = str(random.randint(0,9))
# 随机选取一个字符
tmp = random.choice([upper_str,random_int,lower_str])
# 向图片中写入一个((x轴,y轴)坐标,文本,图片北京,字体样式)
img_draw.text((i*60+60,0),tmp,get_random(),img_font)
# 存储写的字
code += tmp
print(code)
# 这个验证码后面的其他视图函可能用得上,找到地方保存,并且这个地方的全局视图函数都可以访问
request.session['code'] = code
# 图片保存
io_obj = BytesIO()
img_obj.save(io_obj,'png')
return HttpResponse(io_obj.getvalue())
1209 BBS 登录的更多相关文章
- BBS登录功能
BBS登录功能 一.后端实现 1.实现验证码 from PIL import Image, ImageDraw, ImageFont import random from io import Byte ...
- BBS登录与注册功能
登录功能 视图函数 def my_login(request): if request.method == 'GET': return render(request, 'login.html') el ...
- ucenter用户登录过程
以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同. 从用户xxx在某一应用程序的login.php,输入用户名,密码讲起.先用uc_user_login函数到uc_server验证此用户和 ...
- B/S系统间跨域单点登录设计思路
基于B/S系统间单点登录 此处说的单点登录的概念,即不同系统公用一个登录界面.一处系统通过登录验证,在接入的各系统均为登录状态.一般有两种情景: 1) 一级域名相同 例如:tieba.baidu.c ...
- HttpClient相关
HTTPClient的主页是http://jakarta.apache.org/commons/httpclient/,你可以在这里得到关于HttpClient更加详细的信息 HttpClient入门 ...
- HttpClient,DefaultHttpClient使用详解
HttpClient:是一个接口 首先需要先创建一个DefaultHttpClient的实例 HttpClient httpClient=new DefaultHttpClient(); 发送GET请 ...
- php的cookie和session相同主域名共享
如何使用chrome查看cookie和session详见另一篇文章,点这里 首先说cookie, $cookieDomain = '.elf.com'; setcookie('elf', 'im el ...
- uc_client是如何与UCenter进行通信的
以用户登录为例介绍,其它注销,改密码,消息,头像,好友均类同. 从用户xxx在某一应用程序的login.php,输入用户名,密码讲起.先用uc_user_login函数到uc_server验证此用户和 ...
- httpclient详细介绍
1.HttpClient简介 HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 ...
随机推荐
- 【视频开发】OpenCV中Mat,图像二维指针和CxImage类的转换
在做图像处理中,常用的函数接口有OpenCV中的Mat图像类,有时候需要直接用二维指针开辟内存直接存储图像数据,有时候需要用到CxImage类存储图像.本文主要是总结下这三类存储方式之间的图像数据的转 ...
- linux echo -e 处理特殊字符
linux echo -e 处理特殊字符 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:\a 发出警告声:\b 删除前一个字符:\c 最后不加上换行符号:\f 换行但光标仍旧停留 ...
- SpringMVC的拦截器讲解
Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理. 用户可以自己定义一些拦截器来实现特定的功能. 谈到拦截器,还要向大家提一个词 ...
- docker+k8s基础篇五
Docker+K8s基础篇(五) service资源介绍 A:service资源的工作特性 service的使用 A:service字段介绍 B:ClusterIP的简单使用 C:NodePort的简 ...
- nginx实现tcp负载均衡
1 安装支持库 yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel yum install pcre-d ...
- JavaScript有用的代码片段和trick
浮点数取整 const x = 123.4545; x >> 0; ~~x; x | 0; Math.floor(x); 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math. ...
- Appium移动端自动化测试--使用IDE编辑并强化脚本
目录 Appium客户端安装 安装Python IDE-Pycharm Java IDE 安装 使用隐式等待让用例更稳定 隐式等待 启动Appium非GUI模式:Appium Server 安装Pyt ...
- Build step 'Send files or execute commands over SSH' changed build result to UNSTABLE
删除logs文件夹日志即可
- VirtualBox导入OVA文件文档教程
1 2 修改框住的路径,最好不要在C盘 3 取消检查更新 4 5 6 7 8 9 10 11 等待加载完成:加载完成后 OVA文件导入成功 作者:含笑半步颠√ 博客链接:https://www.cnb ...
- python多线程爬取世纪佳缘女生资料并简单数据分析
一. 目标 作为一只万年单身狗,一直很好奇女生找对象的时候都在想啥呢,这事也不好意思直接问身边的女生,不然别人还以为你要跟她表白啥的,况且工科出身的自己本来接触的女生就少,即使是挨个问遍,样本量也 ...