网站风格特点,wordpress不开放注册,在线学做网站,wordpress怎么生成目录1 注册功能 补充(开放文件夹内) 2 前端登录注册页面复制 4 前端注册功能 1 注册功能
# 分析前端#xff1a;携带数据格式 {mobile:,code:,password}后端#xff1a;-1 视图类---》注册方法-2 序列化类---》校验#xff0c;保存#xff08;表中字段多#xff0c;传的少---…1 注册功能 补充(开放文件夹内) 2 前端登录注册页面复制 4 前端注册功能 1 注册功能
# 分析前端携带数据格式 {mobile:,code:,password}后端-1 视图类---》注册方法-2 序列化类---》校验保存表中字段多传的少---》随机按某种格式生成---》后期修改
视图类
class UserRegisterView(GenericViewSet, CreateModelMixin):serializer_class UserRegisterSerializer# action(methods[POST], detailFalse)# def register(self, request, *args, **kwargs):# ser self.get_serializer(datarequest.data)# ser.is_valid(raise_exceptionTrue)# ser.save()# return APIResponse(msg恭喜您注册成功)# 或者改为action(methods[POST], detailFalse)def register(self, request, *args, **kwargs):# 如果是这样做的话内部执行serializer.data----会走序列化----》# 基于create返回的user做序列化-----》按照fields [mobile, code, password]做序列化# 但是code不是表中的字段就会报错这个时候需要在序列化类中将其反序列化# 即code serializers.CharField(max_length4, min_length4, write_onlyTrue)res super().create(request, *args, **kwargs)return APIResponse(msg恭喜注册成功)
序列化类
class UserRegisterSerializer(serializers.ModelSerializer):# code 不是表中字段code serializers.CharField(max_length4, min_length4, write_onlyTrue)class Meta:model Userfields [mobile, code, password]def validate(self, attrs):# 1 校验验证码是否正确mobile attrs.get(mobile)code attrs.get(code)old_code cache.get(cache_mobile_%s % mobile)if code old_code or code 8888: # 测试阶段万能验证码# 2 组装数据 username必填但是没有,code不是表的字段attrs[username] mobileattrs.pop(code)# 3 返回return attrsdef create(self, validated_data): # 密码是加密的如果重写密码是明文的 validated_datamobilepasswordusernameuser User.objects.create_user(**validated_data)return user补充(开放文件夹内)
#1 为什么要写这个media才能访问-django 默认是不允许前端直接访问项目某个文件夹的-有个static文件夹例外需要额外配置-如果想让用户访问必须配置路由使用serve函数放开path(media/path:path, serve, {document_root: settings.MEDIA_ROOT})-浏览器中访问 meida/icon/1.png---能把settings.MEDIA_ROOT对应的文件夹下的icon/1.png返回给前端path(lqz/path:path, serve, {document_root:os.path.join(BASE_DIR, lqz)})浏览器中访问 lqz/a.txt-----能把项目根路径下lqz对应的文件夹下的a.txt返回给前端# 2 配置文件中 debug作用-开发阶段都是debug为True信息显示更丰富-你访问的路由如果不存在会把所有能访问到的路由都显示出来-程序出了异常错误信息直接显示在浏览器上-自动重启只要改了代码会自动重启-上线阶段肯定要改成False#3 ALLOWED_HOSTS 的作用-只有debug 为Flase时这个必须填-限制后端项目(django项目 )能够部署在哪个ip的机器上写个 * 表示所有地址都可以#4 咱们的项目中为了知道是在调试模式还是在上线模式所以才用的debug这个字段-判断如果是开发阶段可以有个万能验证码# 5 短信登录或注册接口-app 只需要输入手机号和验证码如果账号不存在直接注册成功并且登录成功如果账号存在就是登录-前端传入{mobiel,code}---验证验证码是否正确---》拿着mobile去数据库查询如果能查到说明它注册过了直接签发token返回----》如果查不到没有注册过---》走注册逻辑完成注册---》再签发token返回给前端-这个接口随机生成一个6位密码以短信形式通知用户-这个接口密码为空下次他用账号密码登录不允许登录-后续改密码user.set_password(new_password)2 前端登录注册页面测试
登录注册都写成组件----》在任意页面中都能点击显示登录模态框
写好的组件应该放在那个组件中----》不是页面组件(小组件)
点击登录按钮把Login.vue 通过定位占满全屏透明度设为 0.5 ,纯黑色悲剧覆盖在组件上
在Login.vue点关闭要把Login.vue隐藏起来父子通信之子传父自定义事件2.1 Header.vue templatediv classheaderdiv classsloganp老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活/p/divdiv classnavul classleft-partli classlogorouter-link to/img src../assets/img/head-logo.svg alt/router-link/lili classelespan clickgoPage(/free-course) :class{active: url_path /free-course}免费课/span/lili classelespan clickgoPage(/actual-course) :class{active: url_path /actual-course}实战课/span/lili classelespan clickgoPage(/light-course) :class{active: url_path /light-course}轻课/span/li/uldiv classright-partdivspan clickhandleLogin 登录/spanspan classline|/spanspan注册/span/div/divLogin v-ifloginShow closehandleClose/Login/div/div/templatescript
import Login from /components/Login;export default {name: Header,data() {return {url_path: sessionStorage.url_path || /,loginShow: false,}},methods: {goPage(url_path) {// 已经是当前路由就没有必要重新跳转if (this.url_path ! url_path) {this.$router.push(url_path);}sessionStorage.url_path url_path;},handleLogin(){this.loginShow true},handleClose(){this.loginShow false}},created() {sessionStorage.url_path this.$route.path;this.url_path this.$route.path;},components: {Login}
}
/scriptstyle scoped
.header {background-color: white;box-shadow: 0 0 5px 0 #aaa;
}.header:after {content: ;display: block;clear: both;
}.slogan {background-color: #eee;height: 40px;
}.slogan p {width: 1200px;margin: 0 auto;color: #aaa;font-size: 13px;line-height: 40px;
}.nav {background-color: white;user-select: none;width: 1200px;margin: 0 auto;}.nav ul {padding: 15px 0;float: left;
}.nav ul:after {clear: both;content: ;display: block;
}.nav ul li {float: left;
}.logo {margin-right: 20px;
}.ele {margin: 0 20px;
}.ele span {display: block;font: 15px/36px 微软雅黑;border-bottom: 2px solid transparent;cursor: pointer;
}.ele span:hover {border-bottom-color: orange;
}.ele span.active {color: orange;border-bottom-color: orange;
}.right-part {float: right;
}.right-part .line {margin: 0 10px;
}.right-part span {line-height: 68px;cursor: pointer;
}
/style
2.2 Login.vue
templatediv classloginspan clickcloseX/span/div
/templatescript
export default {name: Login,methods: {close() {this.$emit(close_login)}}}
/scriptstyle scoped
.login {width: 100vw;height: 100vh;position: fixed;top: 0;left: 0;z-index: 10;background-color: rgba(0, 0, 0, 0.5);
}
/style3 前端登录功能
templatediv classlogindiv classboxi classel-icon-close clickclose_login/idiv classcontentdiv classnavspan :class{active: login_method is_pwd} clickchange_login_method(is_pwd)密码登录/spanspan :class{active: login_method is_sms} clickchange_login_method(is_sms)短信登录/span/divel-form v-iflogin_method is_pwdel-inputplaceholder用户名/手机号/邮箱prefix-iconel-icon-userv-modelusernameclearable/el-inputel-inputplaceholder密码prefix-iconel-icon-keyv-modelpasswordclearableshow-password/el-inputel-button typeprimary clicklogin登录/el-button/el-formel-form v-iflogin_method is_smsel-inputplaceholder手机号prefix-iconel-icon-phone-outlinev-modelmobileclearableblurcheck_mobile/el-inputel-inputplaceholder验证码prefix-iconel-icon-chat-line-roundv-modelsmsclearabletemplate slotappendspan classsms clicksend_sms{{ sms_interval }}/span/template/el-inputel-button clickmobile_login typeprimary登录/el-button/el-formdiv classfootspan clickgo_register立即注册/span/div/div/div/div
/templatescript
export default {name: Login,data() {return {username: ,password: ,mobile: ,sms: , // 验证码login_method: is_pwd,sms_interval: 获取验证码,is_send: false,}},methods: {close_login() {this.$emit(close)},go_register() {this.$emit(go)},change_login_method(method) {this.login_method method;},check_mobile() {if (!this.mobile) return;// js正则/正则语法/// 字符串.match(/正则语法/)if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {this.$message({message: 手机号有误,type: warning,duration: 1000,onClose: () {this.mobile ;}});return false;}// 后台校验手机号是否已存在this.$axios({url: this.$settings.BASE_URL user/mobile/check_mobile/?mobile this.mobile,method: get,}).then(response {if (response.data.code 100) {this.$message({message: 账号正常,可以发送短信,type: success,duration: 1000,});// 发生验证码按钮才可以被点击this.is_send true;} else {this.$message({message: 账号不存在,type: warning,duration: 1000,onClose: () {this.mobile ;}})}}).catch(() {});},send_sms() {// this.is_send必须允许发生验证码才可以往下执行逻辑if (!this.is_send) return;// 按钮点一次立即禁用this.is_send false;let sms_interval_time 60;this.sms_interval 发送中...;// 定时器: setInterval(fn, time, args)// 往后台发送验证码this.$axios({url: this.$settings.BASE_URL user/mobile/send_sms/,method: post,data: {mobile: this.mobile}}).then(response {if (response.data.code 100) { // 发送成功let timer setInterval(() {if (sms_interval_time 1) {clearInterval(timer);this.sms_interval 获取验证码;this.is_send true; // 重新回复点击发送功能的条件} else {sms_interval_time - 1;this.sms_interval ${sms_interval_time}秒后再发;}}, 1000);} else { // 发送失败this.sms_interval 重新获取;this.is_send true;this.$message({message: 短信发送失败,type: warning,duration: 3000});}}).catch(() {this.sms_interval 频率过快;this.is_send true;})},login() {if (!(this.username this.password)) {this.$message({message: 请填好账号密码,type: warning,duration: 1500});return false // 直接结束逻辑}this.$axios({url: this.$settings.BASE_URL user/login/mul_login/,method: post,data: {username: this.username,password: this.password,}}).then(response {let username response.data.username;let token response.data.token;this.$cookies.set(username, username, 7d);this.$cookies.set(token, token, 7d);this.$emit(success, response.data);}).catch(error {console.log(error.response.data)})},mobile_login() {if (!(this.mobile this.sms)) {this.$message({message: 请填好手机与验证码,type: warning,duration: 1500});return false // 直接结束逻辑}this.$axios({url: this.$settings.BASE_URL user/login/sms_login/,method: post,data: {mobile: this.mobile,code: this.sms,}}).then(response {if (response.data.code 100) {let username response.data.username;let token response.data.token;this.$cookies.set(username, username, 7d);this.$cookies.set(token, token, 7d);this.$emit(success, response.data);} else {this.$message({message: 登录失败,type: warning,duration: 1500});}}).catch(error {console.log(error.response.data)})}}
}
/scriptstyle scoped
.login {width: 100vw;height: 100vh;position: fixed;top: 0;left: 0;z-index: 10;background-color: rgba(0, 0, 0, 0.5);
}.box {width: 400px;height: 420px;background-color: white;border-radius: 10px;position: relative;top: calc(50vh - 210px);left: calc(50vw - 200px);
}.el-icon-close {position: absolute;font-weight: bold;font-size: 20px;top: 10px;right: 10px;cursor: pointer;
}.el-icon-close:hover {color: darkred;
}.content {position: absolute;top: 40px;width: 280px;left: 60px;
}.nav {font-size: 20px;height: 38px;border-bottom: 2px solid darkgrey;
}.nav span {margin: 0 20px 0 35px;color: darkgrey;user-select: none;cursor: pointer;padding-bottom: 10px;border-bottom: 2px solid darkgrey;
}.nav span.active {color: black;border-bottom: 3px solid black;padding-bottom: 9px;
}.el-input, .el-button {margin-top: 40px;
}.el-button {width: 100%;font-size: 18px;
}.foot span {float: right;margin-top: 20px;color: orange;cursor: pointer;
}.sms {color: orange;cursor: pointer;display: inline-block;width: 70px;text-align: center;user-select: none;
}
/style 4 前端注册功能
templatediv classregisterdiv classboxi classel-icon-close clickclose_register/idiv classcontentdiv classnavspan classactive新用户注册/span/divel-formel-inputplaceholder手机号prefix-iconel-icon-phone-outlinev-modelmobileclearableblurcheck_mobile/el-inputel-inputplaceholder密码prefix-iconel-icon-keyv-modelpasswordclearableshow-password/el-inputel-inputplaceholder验证码prefix-iconel-icon-chat-line-roundv-modelsmsclearabletemplate slotappendspan classsms clicksend_sms{{ sms_interval }}/span/template/el-inputel-button clickregister typeprimary注册/el-button/el-formdiv classfootspan clickgo_login立即登录/span/div/div/div/div
/templatescript
export default {name: Register,data() {return {mobile: ,password: ,sms: ,sms_interval: 获取验证码,is_send: false,}},methods: {close_register() {this.$emit(close, false)},go_login() {this.$emit(go)},check_mobile() {if (!this.mobile) return;// js正则/正则语法/// 字符串.match(/正则语法/)if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {this.$message({message: 手机号有误,type: warning,duration: 1000,onClose: () {this.mobile ;}});return false;}// 后台校验手机号是否已存在this.$axios({url: this.$settings.BASE_URL user/mobile/check_mobile/?mobilethis.mobile,method: get,}).then(response {if (response.data.code!100) {this.$message({message: 欢迎注册我们的平台,type: success,duration: 1500,});// 发生验证码按钮才可以被点击this.is_send true;} else {this.$message({message: 账号已存在请直接登录,type: warning,duration: 1500,})}}).catch(() {});},send_sms() {// this.is_send必须允许发生验证码才可以往下执行逻辑if (!this.is_send) return;// 按钮点一次立即禁用this.is_send false;let sms_interval_time 60;this.sms_interval 发送中...;// 定时器: setInterval(fn, time, args)// 往后台发送验证码this.$axios({url: this.$settings.BASE_URL user/mobile/send_sms/,method: post,data: {mobile: this.mobile}}).then(response {if (response.data.code100) { // 发送成功let timer setInterval(() {if (sms_interval_time 1) {clearInterval(timer);this.sms_interval 获取验证码;this.is_send true; // 重新回复点击发送功能的条件} else {sms_interval_time - 1;this.sms_interval ${sms_interval_time}秒后再发;}}, 1000);} else { // 发送失败this.sms_interval 重新获取;this.is_send true;this.$message({message: 短信发送失败,type: warning,duration: 3000});}}).catch(() {this.sms_interval 频率过快;this.is_send true;})},register() {if (!(this.mobile this.sms this.password)) {this.$message({message: 请填好手机、密码与验证码,type: warning,duration: 1500});return false // 直接结束逻辑}this.$axios({url: this.$settings.BASE_URL user/register/register/,method: post,data: {mobile: this.mobile,code: this.sms,password: this.password}}).then(response {this.$message({message: 注册成功3秒跳转登录页面,type: success,duration: 3000,showClose: true,onClose: () {// 去向成功页面this.$emit(success)}});}).catch(error {this.$message({message: 注册失败请重新注册,type: warning,duration: 1500,showClose: true,onClose: () {// 清空所有输入框this.mobile ;this.password ;this.sms ;}});})}}
}
/scriptstyle scoped
.register {width: 100vw;height: 100vh;position: fixed;top: 0;left: 0;z-index: 10;background-color: rgba(0, 0, 0, 0.3);
}.box {width: 400px;height: 480px;background-color: white;border-radius: 10px;position: relative;top: calc(50vh - 240px);left: calc(50vw - 200px);
}.el-icon-close {position: absolute;font-weight: bold;font-size: 20px;top: 10px;right: 10px;cursor: pointer;
}.el-icon-close:hover {color: darkred;
}.content {position: absolute;top: 40px;width: 280px;left: 60px;
}.nav {font-size: 20px;height: 38px;border-bottom: 2px solid darkgrey;
}.nav span {margin-left: 90px;color: darkgrey;user-select: none;cursor: pointer;padding-bottom: 10px;border-bottom: 2px solid darkgrey;
}.nav span.active {color: black;border-bottom: 3px solid black;padding-bottom: 9px;
}.el-input, .el-button {margin-top: 40px;
}.el-button {width: 100%;font-size: 18px;
}.foot span {float: right;margin-top: 20px;color: orange;cursor: pointer;
}.sms {color: orange;cursor: pointer;display: inline-block;width: 70px;text-align: center;user-select: none;
}
/style
Header.vue
templatediv classheaderdiv classsloganp老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活/p/divdiv classnavul classleft-partli classlogorouter-link to/img src../assets/img/head-logo.svg alt/router-link/lili classelespan clickgoPage(/free-course) :class{active: url_path /free-course}免费课/span/lili classelespan clickgoPage(/actual-course) :class{active: url_path /actual-course}实战课/span/lili classelespan clickgoPage(/light-course) :class{active: url_path /light-course}轻课/span/li/uldiv classright-partdiv v-if!usernamespan clickhandleLogin登录/spanspan classline|/spanspan clickhandleRegister注册/span/divdiv v-elsespan{{ username }}/spanspan classline|/spanspan clicklogOut注销/span/div/divLogin v-ifloginShow closehandleClose successsuccess_login gogo_register/LoginRegister v-ifregisterShow closehandleRegisterClose successsuccess_registergosuccess_register/Register/div/div/template
script
import Login from /components/Login.vue;
import Register from /components/Register.vue;export default {name: Header,data() {return {url_path: sessionStorage.url_path || /,loginShow: false,registerShow: false,username: ,token: }},methods: {handleRegister() {this.registerShow true},handleRegisterClose() {this.registerShow false},success_register() {this.registerShow falsethis.loginShow true},go_register() {this.registerShow truethis.loginShow false},logOut() {this.username this.token this.$cookies.remove(username)this.$cookies.remove(token)},goPage(url_path) {// 已经是当前路由就没有必要重新跳转if (this.url_path ! url_path) {this.$router.push(url_path);}sessionStorage.url_path url_path;},handleLogin() {this.loginShow true},handleClose() {this.loginShow false},success_login(data) {this.loginShow false; // 模态框消耗this.username data.username;this.token data.token;}},created() {sessionStorage.url_path this.$route.path;this.url_path this.$route.path;this.username this.$cookies.get(username)},components: {Register,Login}
}
/scriptstyle scoped
.header {background-color: white;box-shadow: 0 0 5px 0 #aaa;
}.header:after {content: ;display: block;clear: both;
}.slogan {background-color: #eee;height: 40px;
}.slogan p {width: 1200px;margin: 0 auto;color: #aaa;font-size: 13px;line-height: 40px;
}.nav {background-color: white;user-select: none;width: 1200px;margin: 0 auto;}.nav ul {padding: 15px 0;float: left;
}.nav ul:after {clear: both;content: ;display: block;
}.nav ul li {float: left;
}.logo {margin-right: 20px;
}.ele {margin: 0 20px;
}.ele span {display: block;font: 15px/36px 微软雅黑;border-bottom: 2px solid transparent;cursor: pointer;
}.ele span:hover {border-bottom-color: orange;
}.ele span.active {color: orange;border-bottom-color: orange;
}.right-part {float: right;
}.right-part .line {margin: 0 10px;
}.right-part span {line-height: 68px;cursor: pointer;
}
/style