南京网站制作公司报价北航刘禹导师做网站
news/
2025/9/23 20:15:26/
文章来源:
南京网站制作公司报价,北航刘禹导师做网站,南昌市住房和城乡建设网站,什么是营销型的网站在上一节中完成了注册功能的前期准备工作#xff0c;在这一节内容中将完成用户注册、登录功能。1.知识预览在本届中将学习到以下内容的知识如何使用wtform来渲染表单如果使用flask-mail来发送邮件2.用户注册在前端中form表单是用的比较多的东西#xff0c;我们可以使用wtform…在上一节中完成了注册功能的前期准备工作在这一节内容中将完成用户注册、登录功能。1.知识预览在本届中将学习到以下内容的知识如何使用wtform来渲染表单如果使用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(min1, max16, message用户名长度限定在1-16位之间),Regexp(^[a-zA-Z0-9_]*$,message用户名只能包含数字、字母以及下划线.)],render_kw{placeholder: 请输入用户名长度1-16之间})nickname StringField(u昵称,validators[DataRequired(message昵称不能为空),Length(min1, max20, 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 typesubmit具体可以去看wtforms的官方文档。继续在上面的文件中嵌入如下代码新建注册表单类class RegisterForm(FlaskForm):user_name StringField(u用户名,validators[DataRequired(message用户名不能为空),Length(min1, max16, message用户名长度限定在1-16位之间),Regexp(^[a-zA-Z0-9_]*$,message用户名只能包含数字、字母以及下划线.)],render_kw{placeholder: 请输入用户名长度1-16之间})nickname StringField(u昵称,validators[DataRequired(message昵称不能为空),Length(min1, max20, message昵称长度限定在1-16位之间)],render_kw{placeholder: 请输入昵称长度1-20之间})user_email StringField(u注册邮箱,validators[DataRequired(message注册邮箱不能为空),Length(min4, message注册邮箱长度必须大于4)],render_kw{placeholder: 请输入注册邮箱, type: email})password StringField(u密码,validators[DataRequired(message用户密码不能为空),Length(min8, max40, message用户密码长度限定在8-40位之间),EqualTo(confirm_pwd, message两次密码不一致)],render_kw{placeholder: 请输入密码, type: password})confirm_pwd StringField(u确认密码,validators[DataRequired(message用户密码不能为空),Length(min8, max40, 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(usernamefiled.data).first():raise ValidationError(用户名已被注册.)def validate_user_email(self, filed):if User.query.filter_by(emailfiled.data.lower()).first():raise ValidationError(邮箱已被注册.)def validate_nickname(self, filed):if User.query.filter_by(nicknamefiled.data).first():raise ValidationError(昵称已被注册)因为学院的选项有许多我们可以在类的构造函数中通过数据库去获取数据库中已经存在的学院然后将其设置到colleges类属性的choices值上这样当我们打开页面渲染表单时数据就会自动渲染到select标签option上去了如下图然后还新建了三个函数validate_user_name、validate_user_email以及validate_nickname这三个函数主要是用来判断email、username、nickname三个字段的唯一性因为在数据库建表的时候将这三个字段设置为uniqueTrue因此在这里需要做一个唯一性的判断。使用wtforms时我们可以通过validate_加上你需要校验的属性字段名称来检验前端用户输入的数据是否符合标准。表单类的编写已经完成接下来就是整个注册逻辑的实现了。新建bbs/templates/frontend/register.html文件嵌入以下代码{% extends frontend/base.html %}
{% import bootstrap/wtf.html as wtf %}
{% block title %}用户注册
{% endblock %}
{% block content %}bodymaindiv classcontainerdiv classjumbotron pt-5 pb-1 mt-2div classrowdiv classcol-md-8h3 classtext-mutedb欢迎注册加入狗子学院~/b/h3hr classbg-primarypb在这里你可以:/b/pulli浏览当下校园的一些趣事、杂谈以及谁和谁的八卦/lili发布一些咸鱼交易、寻物启事等等/lili发现臭味相投的朋友、开拓自己的圈子/li/ulimg src{{ url_for(static, filenameimg/index.jpg) }} classrounded img-fluid/divdiv classcol-md-4div classcard mb-3 w-100 bg-lightdiv classcard-headerh4 classtext-mutedstrong用户注册/strong/h4/divdiv classcard-body{% include _flash.html %}form classbs-component action/auth/register/ methodpost{{ 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 forcaptcha验证码/labeldiv classinput-groupinput typetext classform-control namecaptcha idcaptcha placeholder请输入验证码 aria-requiredtrue aria-describedbycaptcha requireddiv classinput-group-appendbutton classbtn btn-success onclicksendCapt() idsendCaptcha发送/button/div/divp classp-hint验证码发送成功,10分钟内有效!/p{{ form.submit }}hrsmall已有账号? a styletext-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, collegescolleges, formform)在后端代码中我们通过render_template函数返回了前端注册页面并且携带注册表单的实例参数。在前端html文件中我们可以通过form.参数名的方式来进行表单渲染。同时还在前端文件中导入了bootstrap/wtf.html这样就可以将表单的样式渲染成bootstrap的样式当然也可以不是bootstrap/wtf.html来渲染在后端表单类中可以通过render_kw参数来指定我们表单的一些特定参数。在前端页面中我们还手动加入了一行验证码输入框点击发送按钮就可以将验证码发送到用户填写的邮箱当中去了。为什么不将此输入框写到后端表单中去因为那样不好处理前端样式了。访问http://127.0.0.1/auth/register/ 将会看到如下页面在注册页面中是需要用户填写邮箱收到的验证码因此我们需要在后端代码中实现发送邮件的功能。发送邮件的功能是通过flask-email来实现的打开bbs/extensions.py文件加入下面的代码然后在__init__.py文件中进行注册。from flask_mail import Mail
mail Mail()在使用发送邮件功能之前首先我们需要到qq邮箱或者网易邮箱或者其他可以使用的邮箱申请SMTP服务具体流程可以某度某歌搜索一下这里就不再累述。将申请到的私密信填入到.env文件中MAIL_SERVERsmtp.qq.com
MAIL_USERNAME你的qq邮箱名
MAIL_PASSWORDqq邮箱秘钥不是登录密码是申请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],sendercurrent_app.config[MAIL_USERNAME])message.body render_template(template .txt, **kwargs)message.html render_template(template .html, **kwargs)th Thread(targetasync_send_mail, args(current_app._get_current_object(), message))th.start()return th在send_email函数中使用了render_template()来渲染了邮件消息body以及html参数因此需要先将这两个模板准备好。新建bbs/templates/email/verifyCode.html 与bbs/templates/email/verifyCode.txt 文件将下面的代码写到文件中去verifyCode.html h3 stylefont-weight: bold;font-size: 18pxHello {{ username }},/h3
pWelcome to join the a hrefhttp://bbs.2dogz.cn狗子学院/a!This is your register captcha below here./p
h1strong{{ ver_code }}/strong/h1
h5biThe captcha will expire after 10 minutes./i/b/h5
p stylecolor: 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, Collegenormal_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_mailto_email, subjectCaptcha, templateemail/verifyCode, usernameusername,ver_codever_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(minutes10)verify_code VerifyCode(valver_code, whoto_email, expire_timeet)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
scriptlet 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/发送请求同时将email与username传递到后端同时将发送验证码按钮置为不可点击状态间隔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(usernameusername,college_idcollege,nicknamenickname,emailemail,passwordpassword,status_id1)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 %}bodymaindiv classcontainer{% include _flash.html %}div classjumbotron pt-5 pb-3 mt-5div classrowdiv classcol-md-8img src{{ url_for(static, filenameimg/index.jpg) }} classrounded img-fluid/divdiv classcol-md-4div classcard mb-3 w-100 bg-light align-self-centerdiv classcard-headerh4 classtext-mutedstrong用户登录/strong/h4/divdiv classcard-body form classbs-component action/auth/login/ methodpost{{ form.csrf_token }}{{ wtf.form_field(form.usr_email) }}{{ wtf.form_field(form.password) }}{{ wtf.form_field(form.remember_me) }}{{ form.submit }}hrsmall没有账号? a styletext-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(min8, max40, 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, formform)关于登录逻辑处理flask有一个十分流行好用的第三方库flask-login使用该第三库我们可以很方便的处理登录、退出权限控制等操作。首先通过current_user来判断用户是否已经登录了如果登录则返回主页面。接着通过LoginForm示例来获取前端登录页面传递过来的值从数据库获取用户的相关信息首先判断账号是否被禁用了如果被禁用则弹出提示信息并返回给前端页面。接着判断用户密码是否匹配如果不匹配则返回登录页面并提示用户密码不匹配反之则重定向到主页。这里的登录成功重定向其实可以做的更加人性化当用户进入到需要登录才能操作的页面时候这时候会自动跳转到登录页面。如果用户登录成功应该是返回前一个页面而不是固定返回主页。flask_login的login_required装饰器重定向到登录页面的时候会带一个next参数因此我们可以通过此参数来让用户登录成功之后重定向到上一页具体实现很简单就请读者自主开发吧!这时候我们打开登录页面可以看到如下页面到此用户登录注册功能就已经全部实现了下一节将开始讲述论坛主页的实现。教程中的资源文件可以进入我的github仓库下载源代码使用 仓库连接github.com论坛已经基本完成了我已经部署到我的个人服务器上去了主页 -二狗学院bbs.2dogz.cn感兴趣的同学可以关注我的博客网站哦会不定期更新一些程序员相关的博客哦!Home - Blogin2dogz.cn
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/913764.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!