flask 检测post是否为空_使用Flask搭建一个校园论坛-4

4738cd92011f4956654fda2ac0615e52.png

在上一节中完成了注册功能的前期准备工作,在这一节内容中将完成用户注册、登录功能。

1.知识预览

在本届中将学习到以下内容的知识

  1. 如何使用wtform来渲染表单
  2. 如果使用flask-mail来发送邮件

2.用户注册

在前端中form表单是用的比较多的东西,我们可以使用wtforms这个框架,直接通过后端代码来渲染前端表单。新建bbs/forms.py文件,嵌入以下代码

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, SelectField, BooleanField, TextAreaField, FileField, Label, HiddenField, PasswordFieldclass BaseUserForm(FlaskForm):user_name = StringField(u'用户名',validators=[DataRequired(message='用户名不能为空'),Length(min=1, max=16, message='用户名长度限定在1-16位之间'),Regexp('^[a-zA-Z0-9_]*$',message='用户名只能包含数字、字母以及下划线.')],render_kw={'placeholder': '请输入用户名长度1-16之间'})nickname = StringField(u'昵称',validators=[DataRequired(message='昵称不能为空'),Length(min=1, max=20, message='昵称长度限定在1-20位之间')],render_kw={'placeholder': '请输入昵称长度1-20之间'})user_email = StringField(u'注册邮箱',render_kw={'placeholder': '请输入注册邮箱', 'type': 'email'})submit = SubmitField(u'注册', render_kw={'class': 'btn btn-success btn-xs'})

在上面的代码中,首先导入相关的库,然后新建了一个BaseUserForm的类,因为用户的信息在很多表单中使用到了,因此可以将共同的属性剥离出来,然后在不同的场合继承该基类,并且可以根据不同的场合在子类中定制我们的表单属性,这样就可以降低代码的冗余量。如果在每个需要使用到用户信息的表单代码中写入同样的内容,那么久显得代码很臃肿了。

BaseUserForm类中使用到了wtforms中的一些属性,比如StringField就相当于是我们前端的input标签,SubmitField就相当于是<input type="submit">,具体可以去看wtforms的官方文档。

继续在上面的文件中嵌入如下代码,新建注册表单类

class RegisterForm(FlaskForm):user_name = StringField(u'用户名',validators=[DataRequired(message='用户名不能为空'),Length(min=1, max=16, message='用户名长度限定在1-16位之间'),Regexp('^[a-zA-Z0-9_]*$',message='用户名只能包含数字、字母以及下划线.')],render_kw={'placeholder': '请输入用户名长度1-16之间'})nickname = StringField(u'昵称',validators=[DataRequired(message='昵称不能为空'),Length(min=1, max=20, message='昵称长度限定在1-16位之间')],render_kw={'placeholder': '请输入昵称长度1-20之间'})user_email = StringField(u'注册邮箱',validators=[DataRequired(message='注册邮箱不能为空'),Length(min=4, message='注册邮箱长度必须大于4')],render_kw={'placeholder': '请输入注册邮箱', 'type': 'email'})password = StringField(u'密码',validators=[DataRequired(message='用户密码不能为空'),Length(min=8, max=40, message='用户密码长度限定在8-40位之间'),EqualTo('confirm_pwd', message='两次密码不一致')],render_kw={'placeholder': '请输入密码', 'type': 'password'})confirm_pwd = StringField(u'确认密码',validators=[DataRequired(message='用户密码不能为空'),Length(min=8, max=40, message='用户密码长度限定在8-40位之间')],render_kw={'placeholder': '输入确认密码', 'type': 'password'})colleges = SelectField(u'学院', choices=[(1, '计算机')])submit = SubmitField(u'注册', render_kw={'class': 'source-button btn btn-primary btn-xs mt-2'})def __init__(self, *args, **kwargs):super(RegisterForm, self).__init__(*args, **kwargs)cols = College.query.all()self.colleges.choices = [(col.id, col.name) for col in cols]def validate_user_name(self, filed):if User.query.filter_by(username=filed.data).first():raise ValidationError('用户名已被注册.')def validate_user_email(self, filed):if User.query.filter_by(email=filed.data.lower()).first():raise ValidationError('邮箱已被注册.')def validate_nickname(self, filed):if User.query.filter_by(nickname=filed.data).first():raise ValidationError('昵称已被注册')

因为学院的选项有许多,我们可以在类的构造函数中通过数据库去获取数据库中已经存在的学院,然后将其设置到colleges类属性的choices值上,这样当我们打开页面渲染表单时,数据就会自动渲染到select标签option上去了,如下图

f7750aa7ba56f32cdb45f5860a45a7e7.png

然后还新建了三个函数validate_user_namevalidate_user_email以及validate_nickname,这三个函数主要是用来判断email、username、nickname三个字段的唯一性,因为在数据库建表的时候将这三个字段设置为unique=True,因此在这里需要做一个唯一性的判断。

使用wtforms时,我们可以通过validate_加上你需要校验的属性字段名称来检验前端用户输入的数据是否符合标准。

表单类的编写已经完成,接下来就是整个注册逻辑的实现了。新建bbs/templates/frontend/register.html文件,嵌入以下代码

{% extends "frontend/base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}用户注册
{% endblock %}
{% block content %}<body><main><div class="container"><div class="jumbotron pt-5 pb-1 mt-2"><div class="row"><div class="col-md-8"><h3 class="text-muted"><b>欢迎注册加入狗子学院~</b></h3><hr class="bg-primary"><p><b>在这里你可以:</b></p><ul><li>浏览当下校园的一些趣事、杂谈以及谁和谁的八卦</li><li>发布一些咸鱼交易、寻物启事等等</li><li>发现臭味相投的朋友、开拓自己的圈子</li></ul><img src="{{ url_for('static', filename='img/index.jpg') }}" class="rounded img-fluid"></div><div class="col-md-4"><div class="card mb-3 w-100 bg-light"><div class="card-header"><h4 class="text-muted"><strong>用户注册</strong></h4></div><div class="card-body">{% include "_flash.html" %}<form class="bs-component" action="/auth/register/" method="post">{{ form.csrf_token }}{{ wtf.form_field(form.user_name) }}{{ wtf.form_field(form.nickname) }}{{ wtf.form_field(form.user_email) }}{{ wtf.form_field(form.password) }}{{ wtf.form_field(form.confirm_pwd) }}{{ wtf.form_field(form.colleges) }}<label for="captcha">验证码</label><div class="input-group"><input type="text" class="form-control" name="captcha" id="captcha" placeholder="请输入验证码" aria-required="true" aria-describedby="captcha" required><div class="input-group-append"><button class="btn btn-success" onclick="sendCapt()" id="sendCaptcha">发送</button></div></div><p class="p-hint">验证码发送成功,10分钟内有效!</p>{{ form.submit }}<hr><small>已有账号? <a style="text-decoration: none;" href="{{ url_for('.login') }}">登录.</a></small></form></div></div></div></div></div></div></main>

然后打开bbs/blueprint/frontend/auth.py文件,接着在上一节下面嵌入如下代码

@auth_bp.route('/register/', methods=['GET', 'POST'])
def register():colleges = College.query.all()form = RegisterForm()return render_template('frontend/register.html', colleges=colleges, form=form)

在后端代码中我们通过render_template函数返回了前端注册页面,并且携带注册表单的实例参数。在前端html文件中,我们可以通过form.参数名的方式来进行表单渲染。同时还在前端文件中导入了bootstrap/wtf.html,这样就可以将表单的样式渲染成bootstrap的样式,当然也可以不是bootstrap/wtf.html来渲染,在后端表单类中可以通过render_kw参数来指定我们表单的一些特定参数。

在前端页面中我们还手动加入了一行验证码输入框,点击发送按钮就可以将验证码发送到用户填写的邮箱当中去了。为什么不将此输入框写到后端表单中去?因为那样不好处理前端样式了。

访问http://127.0.0.1/auth/register/ 将会看到如下页面:

9dcc597975ab0489f47b9e0ca07e2a58.png

在注册页面中是需要用户填写邮箱收到的验证码,因此我们需要在后端代码中实现发送邮件的功能。发送邮件的功能是通过flask-email来实现的,打开bbs/extensions.py文件,加入下面的代码,然后在__init__.py文件中进行注册。

from flask_mail import Mail
mail = Mail()

在使用发送邮件功能之前,首先我们需要到qq邮箱或者网易邮箱或者其他可以使用的邮箱申请SMTP服务,具体流程可以某度某歌搜索一下,这里就不再累述。将申请到的私密信填入到.env文件中

MAIL_SERVER='smtp.qq.com'
MAIL_USERNAME='你的qq邮箱名'
MAIL_PASSWORD='qq邮箱秘钥不是登录密码是申请SMTP那串无规则秘钥'

然后在bbs/setting.py文件中加入下面的代码

class BaseConfig(object):    # 省略之前代码BBS_MAIL_SUBJECT_PRE = '[狗子学院]'MAIL_SERVER = os.getenv('MAIL_SERVER')MAIL_PORT = 465MAIL_USE_SSL = TrueMAIL_USERNAME = os.getenv('MAIL_USERNAME')MAIL_PASSWORD = os.getenv('MAIL_PASSWORD')MAIL_DEFAULT_SENDER = ('BBS Admin', MAIL_USERNAME)

新建bbs/email.py文件,并将下面代码写入其中。

from threading import Threadfrom bbs.extensions import mail
from flask_mail import Message
from flask import current_app, render_templatedef async_send_mail(app, msg):with app.app_context():mail.send(msg)def send_email(to_mail, subject, template, **kwargs):message = Message(current_app.config['BBS_MAIL_SUBJECT_PRE'] + subject,recipients=[to_mail],sender=current_app.config['MAIL_USERNAME'])message.body = render_template(template + '.txt', **kwargs)message.html = render_template(template + '.html', **kwargs)th = Thread(target=async_send_mail, args=(current_app._get_current_object(), message))th.start()return th

在send_email函数中,使用了render_template()来渲染了邮件消息body以及html参数,因此需要先将这两个模板准备好。新建bbs/templates/email/verifyCode.htmlbbs/templates/email/verifyCode.txt 文件,将下面的代码写到文件中去

verifyCode.html

<h3 style="font-weight: bold;font-size: 18px">Hello {{ username }},</h3>
<p>Welcome to join the <a href="http://bbs.2dogz.cn">狗子学院</a>!This is your register captcha below here.</p>
<h1><strong>{{ ver_code }}</strong></h1>
<h5><b><i>The captcha will expire after 10 minutes.</i></b></h5>
<p style="color: red; font-style: italic"> If this operate is not by yourself, please change your password right now!Maybe your account was cracked.</p>
<small>(Please do not reply to this notification, this inbox is not monitored.)</small>

verifyCode.txt

Hello {{ username }}
Welcome to Blogin!
Welcome to join the 狗子学院!This is your register captcha below here.
{{ ver_code }}
The captcha will expire after 10 minutes.
If this operate is not by yourself, please change your password right now!Maybe your account was cracked.</p>(Please do not reply to this notification, this inbox is not monitored.)

然后开始编写发送邮件的后端逻辑代码,新建bbs/blueprint/frontend/normal.py 文件,因为发送邮件属于通用行为,因此将其放入normal.py模块中,将以下代码嵌入其中

from flask import Blueprint, send_from_directory, request, jsonify
from bbs.extensions import db
from bbs.email import send_email
from bbs.models import VerifyCode, Gender, Role, College@normal_bp.route('/send-email/', methods=['POST'])
def send():to_email = request.form.get('user_email')username = request.form.get('user_name')ver_code = generate_ver_code()send_email(to_mail=to_email, subject='Captcha', template='email/verifyCode', username=username,ver_code=ver_code)# 判断是否已经存在一个最新的可用的验证码,以确保生效的验证码是用户收到最新邮件中的验证码exist_code = VerifyCode.query.filter(VerifyCode.who == to_email, VerifyCode.is_work == 1).order_by(VerifyCode.timestamps.desc()).first()if exist_code:exist_code.is_work = Falsent = datetime.datetime.now()et = nt + datetime.timedelta(minutes=10)verify_code = VerifyCode(val=ver_code, who=to_email, expire_time=et)db.session.add(verify_code)db.session.commit()return jsonify({'tag': 1, 'info': '邮件发送成功!'})

我们根据请求中的keyword来获取前端发送过来的请求参数,然后调用send_email()函数进行发送邮件,同时将生成的随机验证码放入到邮件消息体中去。

然后判断数据库中是否已经存在了属于该注册用户的验证码,如果有则将它设置为过期的,然后将新的验证码存入到数据库中,并设置过期时间为10分钟。这里是通过MySQL来保存的验证码信息,也有其他方法来保存验证码信息,比如使用redis来保存,redis可以设置字段过期时间,如果达到了这个时间,再去取这个字段的值就会为None。

接着我们来处理前端发送邮件的代码,打开bbs/templates/frontend/register.html文件,加入下面的代码

<main>
...
</main>
<script>let time = 60;let reg = /^w+((-w+)|(.w+))*@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+)*.[A-Za-z0-9]+$/;function sendCapt(){let $sendBtn = $("#sendCaptcha");let $email = $("#user_email");let $username = $("#user_name");if ($username.val() === '' || $email.val() === '' || !reg.test($email.val())){return false;}$sendBtn.attr('disabled', true);getRandomCode($sendBtn);$.ajax({url: '/normal/send-email/',type: 'post',data: {'user_name': $username.val(), 'user_email': $email.val()},success: function (res){if (res.tag){$(".p-hint").slideDown(500).delay(3000).hide(500);}}})}//倒计时function getRandomCode(obj) {if (time === 0) {time = 60;obj.text('发送');obj.attr('disabled', false);return;} else {time--;obj.text(time+'(秒)');}setTimeout(function() {getRandomCode(obj);},1000);}</script>

通过ajax向后端/normal/send-email/发送请求,同时将emailusername传递到后端,同时将发送验证码按钮置为不可点击状态,间隔60s才能发送一次,并在前端页面给用户一个提示信息。这样发送验证码邮件的整个流程就完成了,接下里要处理用户点击注册按钮之后的逻辑。

我们使用的是wtfforms来渲染的后端表单,并且在某些表单字段中加入了一些限制信息。在后端代码中,我们可以通过wtfforms的示例来验证我们的表单,打开bbs/blueprint/frontend/auth.py 加入下面的代码

@auth_bp.route('/register/', methods=['GET', 'POST'])
def register():    ...if form.validate_on_submit():username = form.user_name.datanickname = form.nickname.datapassword = form.confirm_pwd.dataemail = form.user_email.datacollege = form.colleges.datacaptcha = request.form.get('captcha')code = VerifyCode.query.filter(VerifyCode.who == email, VerifyCode.is_work == 1).order_by(VerifyCode.timestamps.desc()).first()if code:if code.val != int(captcha):flash('验证码错误!', 'danger')return redirect(request.referrer)elif code.expire_time < datetime.datetime.now():flash('验证码已过期!', 'danger')return redirect(request.referrer)else:flash('请先发送验证码到邮箱!', 'info')return redirect(request.referrer)user = User(username=username,college_id=college,nickname=nickname,email=email,password=password,status_id=1)user.generate_avatar()user.set_password(password)code.is_work = Falsedb.session.add(user)db.session.commit()flash('注册成功,欢迎加入二狗学院!', 'success')return redirect(url_for('.login'))

通过form.validate_on_submit()来判断提交的表单是否通过了验证,通过验证之后通过form.字段名.data来获取对应表单字段的值,然后根据邮箱来查找上一步数据库保存的验证码,如果不存在验证码,则提示用户发送验证码到邮箱,因为存在着一种可能用户乱填一个验证码,而不发送验证码到邮箱。然后判断验证码是否正确或者过期,如果未通过,则发送对应的提示消息提示用户,如果通过,则将用户信息保存到数据库中,然后重定向到登录页面。至此,用户注册的功能就已经完成了。

用户登录

相比注册功能,用户登录就比较简单了。新建bbs/templates/frontend/login.html文件,该文件为用户登录的前端页面模板文件,同样的我们使用wtfforms来渲染表单,在文件中嵌入下面的代码

{% extends "frontend/base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}用户登录
{% endblock %}
{% block content %}<body><main><div class="container">{% include "_flash.html" %}<div class="jumbotron pt-5 pb-3 mt-5"><div class="row"><div class="col-md-8"><img src="{{ url_for('static', filename='img/index.jpg') }}" class="rounded img-fluid"></div><div class="col-md-4"><div class="card mb-3 w-100 bg-light align-self-center"><div class="card-header"><h4 class="text-muted"><strong>用户登录</strong></h4></div><div class="card-body "><form class="bs-component" action="/auth/login/" method="post">{{ form.csrf_token }}{{ wtf.form_field(form.usr_email) }}{{ wtf.form_field(form.password) }}{{ wtf.form_field(form.remember_me) }}{{ form.submit }}<hr><small>没有账号? <a style="text-decoration: none;" href="{{ url_for('.register') }}">注册.</a></small></form></div></div></div></div></div></div></main></body>
{% endblock %}

代码中的form.csrf_token 是一种防止csrf攻击的手段,关于csrf攻击具体可以百度,之后的代码就跟注册模板一样,通过wtfforms进行表单渲染,因此我们需要新建一个渲染登录表单的类,打开bbs/forms.py模块,加入新建登录表单的代码,如下所示

class LoginForm(FlaskForm):usr_email = StringField(u'邮箱/用户名', validators=[DataRequired(message='用户名或邮箱不能为空')],render_kw={'placeholder': '请输入邮箱或用户名'})password = StringField(u'登录密码',validators=[DataRequired(message='登录密码不能为空'),Length(min=8, max=40, message='登录密码必须在8-40位之间')],render_kw={'type': 'password', 'placeholder': '请输入用户密码'})remember_me = BooleanField(u'记住我')submit = SubmitField(u'登录', render_kw={'class': 'source-button btn btn-primary btn-xs'})

接着需要处理后端的登录视图函数,打开bbs/blueprint/frontend/auth.py模块,新建一个视图函数,代码如下所示

from flask_login import current_user, login_user, logout_user
@auth_bp.route('/login/', methods=['GET', 'POST'])
def login():if current_user.is_authenticated:return redirect(url_for('index_bp.index'))form = LoginForm()if form.validate_on_submit():usr = form.usr_email.datapwd = form.password.datauser = User.query.filter(or_(User.username == usr, User.email == usr.lower())).first()if user is not None and user.status.name == '禁用':flash('您的账号处于封禁状态,禁止登陆!联系管理员解除封禁!', 'danger')return redirect(url_for('.login'))if user is not None and user.check_password(pwd):if login_user(user, form.remember_me.data):flash('登录成功!', 'success')return redirect(url_for('index_bp.index'))elif user is None:flash('无效的邮箱或用户名.', 'danger')else:flash('无效的密码', 'danger')return render_template('frontend/login.html', form=form)

关于登录逻辑处理,flask有一个十分流行好用的第三方库flask-login,使用该第三库我们可以很方便的处理登录、退出权限控制等操作。

首先通过current_user来判断用户是否已经登录了,如果登录则返回主页面。接着通过LoginForm示例来获取前端登录页面传递过来的值,从数据库获取用户的相关信息,首先判断账号是否被禁用了,如果被禁用则弹出提示信息,并返回给前端页面。接着判断用户密码是否匹配,如果不匹配则返回登录页面,并提示用户密码不匹配,反之则重定向到主页。

这里的登录成功重定向其实可以做的更加人性化,当用户进入到需要登录才能操作的页面时候,这时候会自动跳转到登录页面。如果用户登录成功,应该是返回前一个页面而不是固定返回主页。flask_login的login_required装饰器重定向到登录页面的时候会带一个next参数,因此我们可以通过此参数来让用户登录成功之后重定向到上一页,具体实现很简单,就请读者自主开发吧!

这时候我们打开登录页面,可以看到如下页面

9023412adfa6e8bb87ebd5b8f4513a52.png

到此,用户登录注册功能就已经全部实现了,下一节将开始讲述论坛主页的实现。

教程中的资源文件可以进入我的github仓库下载源代码使用

仓库连接​github.com

论坛已经基本完成了,我已经部署到我的个人服务器上去了

主页 -二狗学院​bbs.2dogz.cn

感兴趣的同学可以关注我的博客网站哦,会不定期更新一些程序员相关的博客哦!

Home - Blogin​2dogz.cn
073ab62bb93cd2f86ac5e5f5b998dec7.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368480.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL Table 自动生成Net底层-生成数据操作Repository

生成接口类 public static string DataTableToBaseIService(string tableName, string nameSpace, string className){var table SqlTableHelper.GetSQLTableInfo(tableName);StringBuilder reval new StringBuilder();reval.AppendFormat(" using System; using…

自定义Spring命名空间使JAXB更容易

首先&#xff0c;让我大声说出来&#xff1a; Spring不再是XML繁重的了 。 事实上&#xff0c;如今&#xff0c;您可以使用大量注释&#xff0c; Java配置和Spring Boot来编写几乎没有XML或根本没有XML的Spring应用程序。 认真地停止谈论Spring和XML&#xff0c;这已经成为过去…

利用锚点再点事吧丨

上图 接着HTML代码&#xff1a; <div id"color"> <div id"red">红</div> <div id"yellow">黄</div> <div id"black">黑</div> <div id"green">绿</div> </div>…

javaweb笔记1

转载于:https://www.cnblogs.com/webdev8888/p/9164291.html

以太网数据帧的报尾封装字段是什么_16、90秒快速“读懂”数据包的封装、解封装...

数据转发过程概述数据包在相同网段内或不同网段之间转发所依据的原理基本一致。一、数据帧封装TCP封装(四层)当主机建立了到达目的地的TCP连接后&#xff0c;便开始对应用层数据进行封装。主机A会对待发送的应用数据首先执行加密和压缩等相关操作&#xff0c;之后进行传输层封装…

CSS基本知识(慕课网)

1、注释 注解&#xff1a;CSS中注释/*这里是注释的文字*/ HTML中注释<!--这里是注释的文字--> 2、外部式css样式&#xff0c;写在单独的一个文件中 注解&#xff1a; 外部式css样式(也可称为外联式)就是把css代码写一个单独的外部文件中&#xff0c;这个css样式文件以“…

JMS和Spring:有时很重要的小事情

JmsTemplate和DefaultMessageListenerContainer是用于访问JMS兼容MOM的Spring帮助器。 他们的主要目标是在JMS API之上形成一层&#xff0c;并处理诸如事务管理/消息确认之类的基础结构&#xff0c;并隐藏JMS API的某些重复和笨拙的部分&#xff08;保留在那里&#xff1a; JMS…

css实现3D立方体旋转特效

先来看运行后出来的效果 它是在不停运行的一个立方体 先来看html部分的代码 <div class"rect-wrap"> <!--舞台元素&#xff0c;设置perspective&#xff0c;让其子元素获得透视效果。--><div class"container"> <!-- 容器&#…

Eclipse中的Tomcat:6个流行的“如何”问题

学习新技术总是一个艰难的过程。 当您尝试学习将要相互交互的两种技术时&#xff0c;此过程将变得更加困难。 Tomcat和Eclipse是Java EE开发中最流行的先决条件。 因此&#xff0c;要成为一名专业的开发人员&#xff0c;您需要知道如何使用此对执行最需要的操作以及如何进行一些…

adc分辨率和精度的区别_科普 | 传感器的灵敏度、分辨率和精度三者之间有何区别?...

传感器作为一种检测装置&#xff0c;具有微型化、数字化、智能化、多功能化、系统化、网络化的特点。在现代工业生产尤其是自动化生产过程中&#xff0c;需要各种传感器来监视和控制生产过程中的各个参数&#xff0c;使设备工作在正常状态或最佳状态&#xff0c;并使产品达到最…

Linux上的HotSpot GC线程CPU占用空间

以下问题将测试您对Linux操作系统上运行的Java应用程序的垃圾回收和高CPU故障排除的知识。 当调查过多的GC和/或CPU利用率时&#xff0c;此故障排除技术尤其重要。 它将假定您没有访问高级监视工具的能力&#xff0c;例如Compuware dynaTrace甚至JVisualVM。 将来会介绍使用此类…

tornado-简介和原理

tornado-设计初衷 1. 追求小而精 2. epoll IO多路复用和协程 3. 支持WebSocket 4. 单线程程序(GIL限制&#xff0c;本身某种意义上不启动多进程就是单线程程序) # Python GIL介绍详情 tronado应用场景 1. 大量的http请求连接(大量的用户请求&#xff0c;要求并发性和高性能) tr…

前端学习笔记--HTTP缓存

原文地址&#xff1a;https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hlzh-cn 缓存并重用之前获取的资源的能力是性能优化的一个关键方面。 每个浏览器都自带了 HTTP 缓存实现功能&#xff0c;只需要确保每个服务…

如何用Veripacks替换构建模块

比较下面的两棵树。 在这两种情况下&#xff0c;目标都是拥有一个具有两个独立模块&#xff08; frontend和reporting &#xff09;和一个共享/公用模块&#xff08; domain &#xff09;的应用程序。 frontend的代码不应访问reporting代码&#xff0c;反之亦然。 两个模块都可…

JS的DOM和BOM

* JavaScript分三个部分: ECMAScript标准:JS的基本的语法DOM:Document Object Model --->文档对象模型----操作页面的元素BOM:Browser Object Model----->浏览器对象模型---操作的是浏览器一、DOM对象 文档:把一个html文件看成是一个文档,由于万物皆对象,所以把这个文档看…

数据库(11)-- Hash索引和BTree索引 的区别

索引是帮助mysql获取数据的数据结构。最常见的索引是Btree索引和Hash索引。 不同的引擎对于索引有不同的支持&#xff1a;Innodb和MyISAM默认的索引是Btree索引&#xff1b;而Mermory默认的索引是Hash索引。 Hash索引 哈希索引包含以数组形式组织的 Bucket 集合。 哈希函数将索…

MySQL的复制:MySQL系列之十三

一、MySQL复制相关概念 主从复制&#xff1a;主节点将数据同步到多个从节点级联复制&#xff1a;主节点将数据同步到一个从节点&#xff0c;其他的从节点在向从节点复制数据同步复制&#xff1a;将数据从主节点全部同步到从节点时才返回给用户的复制策略叫同步复制异步复制&…

将NetBeans代码模板弯曲到我的意愿

任何阅读过我关于NetBeans的文章的人都知道&#xff0c;我真的很喜欢NetBeans的众多功能。 但是&#xff0c;最近&#xff0c;我发现自己对NetBeans特定功能的特定问题越来越恼火。 最终&#xff0c;它使我烦恼不已&#xff0c;促使我开始研究如何根据自己的喜好禁用或更改该功…

MySQL安装过程

最近试着重装了下MySQL&#xff0c;安装过程很简单&#xff0c;希望能帮助大家 mysql安装过程 1. 下载&#xff1a; 我下载的是64位系统的zip包&#xff1a; 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 下载zip的包。 下载后解压到对应目录 如&#xff1a;D:…

极简的MyBatis在Spring Boot下的配置

以我的一个项目为例。 0、项目结构&#xff1a; 1、POM中添加MyBatis的依赖&#xff1a; <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.1</version> …