Luffy--------------(鍥?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luffy--------------(鍥?相关的知识,希望对你有一定的参考价值。
鏍囩锛?a href='http://www.mamicode.com/so/1/elf' title='elf'>elf
expand tom sys between hold ble 鐩稿悓 dex涓€.棰戠巼闄愬埗鐭俊鎺ュ彛
settings/dev.py:
# drf閰嶇疆 REST_FRAMEWORK = { # Throttling 鈥?/span>DEFAULT_THROTTLE_RATES鈥?/span>: { 鈥?/span>user鈥?/span>: None, 鈥?/span>anon鈥?/span>: None, 鈥?/span>sms鈥?/span>: 鈥?/span>1/min鈥?/span> }, }
apps/user/throttles.py:
from rest_framework.throttling import SimpleRateThrottle class SMSRateThrottle(SimpleRateThrottle): scope = 鈥?/span>sms鈥?/span> def get_cache_key(self, request, view): # 閽堝鎵嬫満鍙疯繘琛岄檺鍒?/span> mobile = request.data.get(鈥?/span>mobile鈥?/span>) or request.query_params.get(鈥?/span>mobile鈥?/span>) if not mobile: return None return self.cache_format % { 鈥?/span>scope鈥?/span>: self.scope, 鈥?/span>ident鈥?/span>: mobile }
user/views.py:
from libs.txm import get_code, send_sms from django.core.cache import cache from .throttles import SMSRateThrottle from . import models, serializers from settings.const import SMS_CODE_EXC class SMSAPIView(APIView): throttle_classes = [SMSRateThrottle] def post(self, request, *args, **kwargs): # 鎷垮埌鍓嶇鐨勬墜鏈哄彿 mobile = request.data.get(鈥?/span>mobile鈥?/span>) # 瀹屾垚鎵嬫満鍙风殑鏍¢獙锛堟槸鍚﹀悎娉曪級 if not mobile or not re.match(r鈥?/span>^1[3-9][0-9]{9}$鈥?/span>, mobile): return APIResponse(1, 鈥?/span>鎵嬫満鍙锋湁璇?/span>鈥?/span>) # 浜х敓楠岃瘉鐮?/span> code = get_code() # 閫氱煡绗笁鏂瑰彂閫佺煭淇?/span> result = send_sms(mobile, code, SMS_CODE_EXC // 60) # 澶辫触锛氬搷搴斿墠鍙板彂閫佸け璐?/span> if not result: return APIResponse(1, 鈥?/span>鐭俊鍙戦€佸け璐?/span>鈥?/span>) # 鎴愬姛锛氱紦瀛橀獙璇佺爜(鏍¢獙澶囩敤)锛屽搷搴斿墠鍙板彂閫佹垚鍔?/span> cache.set(鈥?/span>%s_code鈥?/span> % mobile, code, SMS_CODE_EXC) # print(cache.get(鈥?s_code鈥?% mobile)) return APIResponse(0, 鈥?/span>鐭俊鍙戦€佹垚鍔?/span>鈥?/span>)
浜?鎵嬫満鍙烽獙璇佹帴鍙?/strong>
鍓嶅彴鎵嬫満鍙锋牎楠宺egister.vue:
methods: { checkMobile() { if (this.mobile.length < 1) { return false; } // 鎵嬫満鍙风爜鏍煎紡鏄惁姝g‘ if (!/^1[3-9]d{9}$/.test(this.mobile)) { this.$message({ message: "瀵逛笉璧凤紒鎵嬫満鍙风爜鏍煎紡鏈夎锛?/span>" }); return false; } // 楠岃瘉鎵嬫満鍙风爜鏄惁宸茬粡娉ㄥ唽浜? this.$axios({ url: this.$settings.base_url + 鈥?/span>/user/mobile/鈥?/span>, method: 鈥?/span>get鈥?/span>, params: { mobile: this.mobile } }).then(response => { let data = response.data; // window.console.log(data); if (data.status != 0) { this.$message({ message: "瀵逛笉璧凤紒鎵嬫満鍙风爜宸茬粡琚敞鍐岋紒", duration: 1000 }); return false; } else { this.$message({ message: "鏈熷緟鎮ㄥ姞鍏ユ垜浠紒", duration: 1000, // onClose: () => { // console.log(鈥?/span>淇℃伅妗嗗叧闂簡鈥?/span>) // } }); } }).catch(error => { let data = error.response.data; this.$message({ message: data.message }) }) }, ...
鍚庡彴鎵嬫満鍙锋牎楠?
user/urls
from django.urls import path from . import views urlpatterns = [ path(鈥?/span>sms/鈥?/span>, views.SMSAPIView.as_view()), path(鈥榤obile/鈥?/span>, views.MobileAPIView.as_view()), ]
user/views.py
class MobileAPIView(APIView): def get(self, request, *args, **kwargs): # 鑾峰彇鎵嬫満鍙?/span> mobile = request.query_params.get(鈥?/span>mobile鈥?/span>) if not mobile: return APIResponse(1, 鈥?/span>鎵嬫満鍙峰繀椤绘彁渚?/span>鈥?/span>) # 鏍¢獙鎵嬫満鍙锋槸鍚﹀悎娉?/span> if not re.match(r鈥?/span>^1[3-9][0-9]{9}$鈥?/span>, mobile): return APIResponse(1, 鈥?/span>鎵嬫満鍙锋湁璇?/span>鈥?/span>) # 鏍¢獙鎵嬫満鍙锋槸鍚﹀瓨鍦?/span> try: models.User.objects.get(mobile=mobile) return APIResponse(1, 鈥?/span>鎵嬫満鍙峰凡娉ㄥ唽鈥?/span>) except: return APIResponse(0, 鈥?/span>鎵嬫満鍙锋湭娉ㄥ唽鈥?/span>)
涓?娉ㄥ唽鎺ュ彛瀹炵幇(鐢ㄦ埛鍚嶆槸鎵嬫満鍙?
settings/const.py:
# 楠岃瘉鐮佽繃鏈熸椂闂达紙s锛?鏇挎崲杩囨湡鏃堕棿 SMS_CODE_EXC = 300000
鍓嶅彴鍙戦€佺煭淇′慨璁egister.vue:
send_sms() { // 鍙戦€佺煭淇? if (!/^1[3-9]d{9}$/.test(this.mobile)) { this.$message({ message: "瀵逛笉璧凤紒鎵嬫満鍙风爜鏍煎紡鏈夎锛?/span>" }); return false; } // 鍒ゆ柇鏄惁鍦?0s鍐呭彂閫佽繃鐭俊 if (this.is_send) { this.$message({ message: "瀵逛笉璧?涓嶈兘棰戠箒鍙戦€佺煭淇¢獙璇侊紒" }); return false; } // 璇锋眰鍙戦€佺煭淇? this.$axios({ url: this.$settings.base_url + 鈥?/span>/user/sms/鈥?/span>, method: 鈥?/span>post鈥?/span>, data: { mobile: this.mobile } }).then(response => { this.$message({ message: response.data.msg, }); // 淇敼鐭俊鐨勫彂閫佺姸鎬? this.is_send = true; // 璁剧疆闂撮殧鏃堕棿60s let sms_interval_time = 60; // 璁剧疆鐭俊鍙戦€侀棿闅斿€掕鏃?.60s鍚庢妸is_send鏀规垚false let timer = setInterval(() => { if (sms_interval_time <= 1) { clearInterval(timer); this.sms_interval_tips = "鑾峰彇楠岃瘉鐮?/span>"; this.is_send = false; // 閲嶆柊鍥炲鐐瑰嚮鍙戦€佸姛鑳界殑鏉′欢 } else { sms_interval_time -= 1; this.sms_interval_tips = `${sms_interval_time}绉掑悗鍐嶆鑾峰彇`; } }, 1000); }).catch(error => { this.$message({ message: error.response.data.result, }) }); },
鍚庡彴娉ㄥ唽鎺ュ彛:
user/ url.py
from django.urls import path from . import views urlpatterns = [ path(鈥?/span>sms/鈥?/span>, views.SMSAPIView.as_view()), path(鈥?/span>mobile/鈥?/span>, views.MobileAPIView.as_view()), path(鈥榬egister/鈥?/span>, views.RegisterAPIView.as_view()), path(鈥?/span>login/鈥?/span>, views.LoginAPIView.as_view()), path(鈥?/span>login/mobile/鈥?/span>, views.LoginMobileAPIView.as_view()), ]
views.py
class RegisterAPIView(APIView): def post(self, request, *args, **kwargs): # 灏嗚姹傛暟鎹?鎵嬫満瀵嗙爜楠岃瘉鐮?=> 璐﹀彿鎵嬫満瀵嗙爜楠岃瘉鐮?/span> request_data = request.data request_data[鈥?/span>username鈥?/span>] = request_data.get(鈥?/span>mobile鈥?/span>) # 鏍¢獙 user_ser = serializers.UserModelSerializer(data=request_data) if user_ser.is_valid(): user_ser.save() return APIResponse(0, 鈥?/span>娉ㄥ唽鎴愬姛鈥?/span>, results=user_ser.data) else: return APIResponse(1, 鈥?/span>娉ㄥ唽澶辫触鈥?/span>, results=user_ser.errors)
搴忓垪鍖栫被user/serializers.py
from rest_framework import serializers from . import models from django.core.cache import cache import re class UserModelSerializer(serializers.ModelSerializer): code = serializers.CharField(write_only=True, min_length=4, max_length=4) class Meta: model = models.User fields = (鈥?/span>username鈥?/span>, 鈥?/span>password鈥?/span>, 鈥?/span>mobile鈥?/span>, 鈥?/span>code鈥?/span>) extra_kwargs = { 鈥?/span>password鈥?/span>: { 鈥?/span>write_only鈥?/span>: True } } def validate_mobile(self, value): if not re.match(r鈥?/span>^1[3-9][0-9]{9}$鈥?/span>, value): raise serializers.ValidationError(鈥?/span>鎵嬫満鍙锋湁璇?/span>鈥?/span>) return value def validate(self, attrs): code = attrs.pop(鈥?/span>code鈥?/span>) mobile = attrs.get(鈥?/span>mobile鈥?/span>) old_code = cache.get(鈥?/span>%s_code鈥?/span> % mobile) if code != old_code: raise serializers.ValidationError({鈥?/span>楠岃瘉鐮?/span>鈥?/span>: 鈥?/span>楠岃瘉鐮佹湁璇?/span>鈥?/span>}) return attrs def create(self, validated_data): return models.User.objects.create_user(**validated_data)
#閲嶅啓create鏂规硶,瀵嗙爜涓哄瘑鏂?/span>
娉?鎵嬫満鍙锋敞鍐屼笉鑳界浉鍚?models.py涓皢mobile瀛楁鍔犱竴涓猽nique=true
娉ㄥ唽鍓嶅彴register.vue:
registerMobile() { // 娉ㄥ唽淇℃伅鎻愪氦 if (!/^1[3-9]d{9}$/.test(this.mobile)) { this.$message({ message: "瀵逛笉璧凤紒鎵嬫満鍙风爜鏍煎紡鏈夎锛?/span>" }); return false; } if (this.sms.length < 1) { this.$message({ message: "鐭俊楠岃瘉鐮佷笉鑳戒负绌猴紒" }); return false; } if (this.password.length < 6 || this.password.length > 16) { this.$message({ message: "瀵逛笉璧凤紝瀵嗙爜闀垮害蹇呴』鍦?-16涓瓧绗︿箣闂达紒" }); return false; } this.$axios({ url: this.$settings.base_url + 鈥?/span>/user/register/鈥?/span>, method: 鈥?/span>post鈥?/span>, data: { mobile: this.mobile, password: this.password, code: this.sms } }).then(response => { let status = response.data.status; let msg = response.data.msg; if (status == 0) { this.$message({ message: msg, duration: 1000, onClose: () => { this.$router.push(鈥?/span>/login鈥?/span>) } }); } else { // 瀹為檯鏍规嵁閿欒淇℃伅锛屾彁绀洪敊璇殑鍏蜂綋杈撳叆妗? this.mobile = 鈥樷€?/span>; this.password = 鈥樷€?/span>; this.sms = 鈥樷€?/span>; this.$message({ message: msg, duration: 1000, }); } }).catch(error => { this.$message({ message: error.response.data.result }); }) } },
鍥?鐧诲綍鎺ュ彛鐨勫疄鐜?/strong>
涓ょ鐧诲綍璺敱:
from django.urls import path from . import views urlpatterns = [ path(鈥?/span>sms/鈥?/span>, views.SMSAPIView.as_view()), path(鈥?/span>mobile/鈥?/span>, views.MobileAPIView.as_view()), path(鈥?/span>register/鈥?/span>, views.RegisterAPIView.as_view()), path(鈥榣ogin/鈥? views.LoginAPIView.as_view()), path(鈥榣ogin/mobile/鈥?/span>, views.LoginMobileAPIView.as_view()), ]
user/views
棣栧厛瀹夎jwt: pip install djangorestframework-jwt
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler class LoginAPIView(APIView): authentication_classes = () permission_classes = () def post(self, request, *args, **kwargs): # username鍙兘鎼哄甫鐨勪笉姝㈡槸鐢ㄦ埛鍚嶏紝鍙兘杩樻槸鐢ㄦ埛鐨勫叾瀹冨敮涓€鏍囪瘑 鎵嬫満鍙?閭 username = request.data.get(鈥?/span>username鈥?/span>) password = request.data.get(鈥?/span>password鈥?/span>) if not (username and password): return APIResponse(1, 鈥?/span>璐﹀彿瀵嗙爜蹇呴』鈥?/span>) # 濡傛灉username鍖归厤涓婃墜鏈哄彿姝e垯 => 鍙兘鏄墜鏈虹櫥褰?/span> if re.match(r鈥?/span>^1[3-9][0-9]{9}$鈥?/span>, username): try: # 鎵嬪姩閫氳繃 user 绛惧彂 jwt-token user = models.User.objects.get(mobile=username) except: return APIResponse(1, 鈥?/span>璇ユ墜鏈烘湭娉ㄥ唽鈥?/span>) # 閭鐧诲綍 绛?/span> # 璐﹀彿鐧诲綍 else: try: # 鎵嬪姩閫氳繃 user 绛惧彂 jwt-token user = models.User.objects.get(username=username) except: return APIResponse(1, 鈥?/span>璇ヨ处鍙锋湭娉ㄥ唽鈥?/span>) # 鑾峰緱鐢ㄦ埛鍚庯紝鏍¢獙瀵嗙爜骞剁鍙憈oken if not user.check_password(password): return APIResponse(1, 鈥?/span>瀵嗙爜閿欒鈥?/span>) payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) return APIResponse(0, 鈥?/span>ok鈥?/span>, results={ 鈥?/span>username鈥?/span>: user.username, 鈥?/span>mobile鈥?/span>: user.mobile, 鈥?/span>token鈥?/span>: token }) class LoginMobileAPIView(APIView): authentication_classes = () permission_classes = () def post(self, request, *args, **kwargs): # 鎵嬫満鍙疯幏鍙栧苟鏍¢獙 mobile = request.data.get(鈥?/span>mobile鈥?/span>) code = request.data.get(鈥?/span>code鈥?/span>) if not (mobile and code): return APIResponse(1, 鈥?/span>鎵嬫満鍙蜂笌楠岃瘉鐮佸繀椤?/span>鈥?/span>) # 楠岃瘉鐮佽幏鍙栧苟鏍¢獙 old_code = cache.get(鈥?/span>%s_code鈥?/span> % mobile) # 楠岃瘉鐮佸疄闄呭紑鍙戝彧鍙互浣跨敤涓€娆?/span> # cache.set(鈥?s_code鈥?% mobile, 鈥?000鈥? 1) if code != old_code: return APIResponse(1, 鈥?/span>楠岃瘉鐮侀敊璇?/span>鈥?/span>) # 閫氳繃鎵嬫満鍙疯幏鍙栫敤鎴?/span> try: user = models.User.objects.get(mobile=mobile) except: return APIResponse(1, 鈥?/span>璇ヨ处鍙锋湭娉ㄥ唽鈥?/span>) # 绛惧彂token payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) return APIResponse(0, 鈥?/span>ok鈥?/span>, results={ 鈥?/span>username鈥?/span>: user.username, 鈥?/span>mobile鈥?/span>: user.mobile, 鈥?/span>token鈥?/span>: token })
鐧诲綍鍓嶅彴login.vue:
<template> <div class="login box"> <img src="@/assets/img/Loginbg.jpg" alt=""> <div class="login"> <div class="login-title"> <img src="@/assets/img/Logotitle.png" alt=""> <p>甯姪鏈夊織鍚戠殑骞磋交浜洪€氳繃鍔姏瀛︿範鑾峰緱浣撻潰鐨勫伐浣滃拰鐢熸椿!</p> </div> <div class="login_box"> <div class="title"> <span :class="{active: a0}" @click="changeLogin(0)">瀵嗙爜鐧诲綍</span> <span :class="{active: a1}" @click="changeLogin(1)">鐭俊鐧诲綍</span> </div> <div class="inp" v-if="login_type==0"> <input v-model="username" type="text" placeholder="鐢ㄦ埛鍚?/ 鎵嬫満鍙风爜" class="user"> <input v-model="password" type="password" name="" class="pwd" placeholder="瀵嗙爜"> <div id="geetest1"></div> <div class="rember"> <p> <input id="checkbox" type="checkbox" class="no" v-model="remember"/> <span>璁颁綇瀵嗙爜</span> </p> <p>蹇樿瀵嗙爜</p> </div> <button class="login_btn" @click="loginAction">鐧诲綍</button> <p class="go_login">娌℃湁璐﹀彿 <router-link to="/register">绔嬪嵆娉ㄥ唽</router-link> </p> </div> <div class="inp" v-show="login_type==1"> <input v-model="mobile" type="text" placeholder="鎵嬫満鍙风爜" class="user"> <div class="sms"> <input v-model="sms" type="text" placeholder="杈撳叆楠岃瘉鐮?/span>" class="user"> <span class="sms_btn" @click="send_sms">{{sms_interval_tips}}</span> </div> <button class="login_btn" @click="loginMobile">鐧诲綍</button> <p class="go_login">娌℃湁璐﹀彿 <router-link to="/register">绔嬪嵆娉ㄥ唽</router-link> </p> </div> </div> </div> </div> </template> <script> export default { name: 鈥?/span>Login鈥?/span>, data() { return { a0: 1, a1: 0, login_type: 0, username: "", password: "", remember: false, mobile: "", sms: "", is_send: false, // 鏄惁鍦?0s鍐呭彂閫佷簡鐭俊 sms_interval_tips: "鑾峰彇楠岃瘉鐮?/span>", } }, created() { // 鎷︽埅宸茬櫥褰曟儏鍐?/span> let token = this.$cookies.get(鈥?/span>token鈥?/span>); if (token) { this.$message({ message: 鈥?/span>鏃犻渶閲嶅鐧诲綍鈥?/span>, duration: 1000, onClose: () => { this.$router.go(-1) } }) } }, methods: { changeLogin(i) { this.login_type = i; if (i) { this.a0 = 0; this.a1 = 1; } else { this.a0 = 1; this.a1 = 0; } }, loginAction() { if (!this.username || !this.password) { return } this.$axios({ url: this.$settings.base_url + 鈥?/span>/user/login/鈥?/span>, method: 鈥?/span>post鈥?/span>, data: { 鈥?/span>username鈥?/span>: this.username, 鈥?/span>password鈥?/span>: this.password } }).then((response) => { // 鍒ゆ柇鐢ㄦ埛鏄惁瑕佽浣忓瘑鐮? if (this.remember) { // 璁颁綇瀵嗙爜,姘稿瓨 sessionStorage.clear(); localStorage.token = response.data.results.token; localStorage.username = response.data.results.username; localStorage.mobile = response.data.results.mobile; } else { /// 娌¤浣忓瘑鐮?鏆傚瓨 localStorage.clear(); sessionStorage.token = response.data.results.token; sessionStorage.username = response.data.results.username; sessionStorage.mobile = response.data.results.mobile; } if (response.data.status == 0) { let token = response.data.results.token; this.$cookies.set(鈥?/span>token鈥?/span>, token, 24 * 60 * 60); let username = response.data.results.username; this.$cookies.set(鈥?/span>username鈥?/span>, username, 24 * 60 * 60); this.$alert("娆㈣繋鍥炴潵锛?/span>", "鐧诲綍鎴愬姛锛?/span>", { confirmButtonText: 鈥?/span>纭畾鈥?/span>, callback: () => { // 鐧诲綍鎴愬姛鍘讳富椤? this.$router.push("/"); } }) } else { this.username = 鈥樷€?/span>; this.password = 鈥樷€?/span>; } }).catch(() => { this.$alert("妫€鏌ヨ处鍙峰瘑鐮侊紒", "鐧诲綍澶辫触锛?/span>", { confirmButtonText: 鈥?/span>纭畾鈥?/span>, callback: () => { this.username = 鈥樷€?/span>; this.password = 鈥樷€?/span>; } }); }) }, send_sms() { // 鍙戦€佺煭淇? if (!/^1[3-9]d{9}$/.test(this.mobile)) { this.$message({ message: "瀵逛笉璧凤紒鎵嬫満鍙风爜鏍煎紡鏈夎锛?/span>" }); return false; } // 鍒ゆ柇鏄惁鍦?0s鍐呭彂閫佽繃鐭俊 if (this.is_send) { this.$message({ message: "瀵逛笉璧?涓嶈兘棰戠箒鍙戦€佺煭淇¢獙璇侊紒" }); return false; } // 璇锋眰鍙戦€佺煭淇? this.$axios({ url: this.$settings.base_url + 鈥?/span>/user/sms/鈥?/span>, method: 鈥?/span>post鈥?/span>, data: { mobile: this.mobile } }).then(response => { let msg = response.data.result; this.$message({ message: msg, }); if (msg === 鈥?/span>鐭俊鍙戦€佸け璐?/span>鈥?/span>) return; // 淇敼鐭俊鐨勫彂閫佺姸鎬? this.is_send = true; // 璁剧疆闂撮殧鏃堕棿60s let sms_interval_time = 60; // 璁剧疆鐭俊鍙戦€侀棿闅斿€掕鏃?.60s鍚庢妸is_send鏀规垚false let timer = setInterval(() => { if (sms_interval_time <= 1) { clearInterval(timer); this.sms_interval_tips = "鑾峰彇楠岃瘉鐮?/span>"; this.is_send = false; // 閲嶆柊鍥炲鐐瑰嚮鍙戦€佸姛鑳界殑鏉′欢 } else { sms_interval_time -= 1; this.sms_interval_tips = `${sms_interval_time}绉掑悗鍐嶆鑾峰彇`; } }, 1000); }).catch(error => { this.$message({ message: error.response.data.result, }) }); }, loginMobile() { // 娉ㄥ唽淇℃伅鎻愪氦 if (!/^1[3-9]d{9}$/.test(this.mobile)) { this.$message({ message: "瀵逛笉璧凤紒鎵嬫満鍙风爜鏍煎紡鏈夎锛?/span>" }); return false; } if (this.sms.length < 1) { this.$message({ message: "鐭俊楠岃瘉鐮佷笉鑳戒负绌猴紒" }); return false; } this.$axios({ url: this.$settings.base_url + 鈥?/span>/user/login/mobile/鈥?/span>, method: 鈥?/span>post鈥?/span>, data: { mobile: this.mobile, code: this.sms } }).then(response => { let _this = this; let status = response.data.status; let msg = response.data.msg; if (status == 0) { // cookie瀛樺偍token锛屼繚瀛樼櫥褰曠姸鎬?/span> let token = response.data.results.token; _this.$cookies.set(鈥榯oken鈥? token, 24 * 60 * 60); let username = response.data.results.username; _this.$cookies.set(鈥榰sername鈥? username, 24 * 60 * 60); _this.$message({ message: 鈥?/span>鐧诲綍鎴愬姛鈥?/span>, duration: 1000, onClose() { // 淇濆瓨鐧诲綍鐘舵€? sessionStorage.token = token; sessionStorage.username = response.data.results.username; sessionStorage.mobile = response.data.results.mobile; // 璺宠浆鍒颁富椤? _this.$router.push(鈥?/span>/鈥?/span>); } }); } else { _this.mobile = 鈥樷€?/span>; _this.sms = 鈥樷€?/span>; _this.$message({ message: msg, }); } }).catch(error => { this.mobile = 鈥樷€?/span>; this.sms = 鈥樷€?/span>; this.$message({ message: error.response.data.result }); }) }, }, }; </script> <style scoped> .box { width: 100%; height: 100%; position: relative; overflow: hidden; } .box img { width: 100%; min-height: 100%; } .box .login { position: absolute; width: 500px; height: 400px; left: 0; margin: auto; right: 0; bottom: 0; top: -338px; } .login .login-title { width: 100%; text-align: center; padding-top: 20px; } .login-title img { width: 190px; height: auto; } .login-title p { font-family: PingFangSC-Regular; font-size: 18px; color: #fff; letter-spacing: .29px; padding-top: 10px; padding-bottom: 50px; } .login_box { width: 400px; height: auto; background: #fff; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .5); border-radius: 4px; margin: 0 auto; padding-bottom: 40px; } .login_box .title { font-size: 20px; color: #9b9b9b; letter-spacing: .32px; border-bottom: 1px solid #e6e6e6; display: flex; justify-content: space-around; padding: 50px 60px 0 60px; margin-bottom: 20px; cursor: pointer; } .login_box .title span.active { color: #4a4a4a; border-bottom: 2px solid #84cc39; } .inp { width: 350px; margin: 0 auto; } .inp input { outline: 0; width: 100%; height: 45px; border-radius: 4px; border: 1px solid #d9d9d9; text-indent: 20px; font-size: 14px; background: #fff !important; } .inp input.user { margin-bottom: 16px; } .inp .rember { display: flex; justify-content: space-between; align-items: center; position: relative; margin-top: 10px; } .inp .rember p:first-of-type { font-size: 12px; color: #4a4a4a; letter-spacing: .19px; margin-left: 22px; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; /*position: relative;*/ } .inp .rember p:nth-of-type(2) { font-size: 14px; color: #9b9b9b; letter-spacing: .19px; cursor: pointer; } .inp .rember input { outline: 0; width: 30px; height: 45px; border-radius: 4px; border: 1px solid #d9d9d9; text-indent: 20px; font-size: 14px; background: #fff !important; } .inp .rember p span { display: inline-block; font-size: 12px; width: 100px; /*position: absolute;*/ /*left: 20px;*/ } #geetest { margin-top: 20px; } .login_btn { width: 100%; height: 45px; background: #84cc39; border-radius: 5px; font-size: 16px; color: #fff; letter-spacing: .26px; margin-top: 30px; } .inp .go_login { text-align: center; font-size: 14px; color: #9b9b9b; letter-spacing: .26px; padding-top: 20px; } .inp .go_login a { color: #84cc39; cursor: pointer; } #get_code { border: 0; width: 120px; height: 30px; background-color: antiquewhite; outline: none; } #get_code:active { color: white; } #checkbox { width: 20px; height: 20px; } .sms { position: relative; } .sms .sms_btn { position: absolute; top: -12px; right: 0; bottom: 0; margin: auto; width: 130px; text-align: center; height: 24px; color: #ff7000; cursor: pointer; border-left: 1px solid #999; } </style>
浜?鍓嶅彴娉ㄩ攢
鍚庡彴token杩囨湡鏃堕棿閰嶇疆dev.py:
# jwt閰嶇疆 import datetime JWT_AUTH = { 鈥?/span>JWT_EXPIRATION_DELTA鈥?/span>: datetime.timedelta(days=1), }
cookie鍦ㄧ櫥褰曟垚鍔熷悗宸蹭繚瀛?/strong>
header.vue:
<template> <div class="header-box"> <div class="header"> <div class="content"> <div class="logo full-left"> <router-link to="/"><img @click="jump(鈥?鈥?" src="@/assets/img/logo.svg" alt=""></router-link> </div> <ul class="nav full-left"> <li><span @click="jump(鈥?course鈥?" :class="this_nav==鈥?course鈥?鈥榯his鈥?鈥樷€?/span>">鍏嶈垂璇?lt;/span></li> <li><span @click="jump(鈥?light-course鈥?" :class="this_nav==鈥?light-course鈥?鈥榯his鈥?鈥樷€?/span>">杞昏</span></li> <li><span>瀛︿綅璇?lt;/span></li> <li><span>棰樺簱</span></li> <li><span>鑰佺敺瀛╂暀鑲?lt;/span></li> </ul> <div class="login-bar full-right"> <div class="shop-cart full-left"> <img src="@/assets/img/cart.svg" alt=""> <span><router-link to="/cart">璐墿杞?lt;/router-link></span> </div> <div class="login-box full-left"> <div v-if="!is_login"> <router-link to="/login">鐧诲綍</router-link> | <router-link to="/register">娉ㄥ唽</router-link> </div> <div v-else> <router-link to="/user">{{ username }}</router-link> | <span @click="logoutAction">娉ㄩ攢</span> </div> </div> </div> </div> </div> </div> </template> <script> export default { name: "Header", data() { return { this_nav: "", is_login: false, username: 鈥樷€?/span>, } }, created() { this.this_nav = localStorage.this_nav; this.is_login = this.$cookies.get(鈥?/span>token鈥?/span>); this.username = this.$cookies.get(鈥?/span>username鈥?/span>); }, methods: { jump(location) { localStorage.this_nav = location; // vue-router闄や簡鎻愪緵router-link鏍囩璺宠浆椤甸潰浠ュ锛岃繕鎻愪緵浜?js璺宠浆鐨勬柟寮? this.$router.push(location); }, logoutAction() { this.is_login = false; this.username = 鈥樷€?/span>; this.$cookies.remove(鈥?/span>token鈥?/span>); this.$cookies.remove(鈥?/span>username鈥?/span>); } } } </script>
鍏?鎺ュ彛缂撳瓨
home/views.py
from rest_framework.generics import ListAPIView from rest_framework.response import Response from . import models, serializers """ class BannerListAPIView(ListAPIView): queryset = models.Banner.objects.filter(is_show=True, is_delete=False).order_by(鈥?orders鈥? serializer_class = serializers.BannerModelSerializer """ # 鎺ュ彛缂撳瓨 from django.core.cache import cache class BannerListAPIView(ListAPIView): def get(self, request, *args, **kwargs): banner_list_data = cache.get(鈥?/span>api_banner_list_data鈥?/span>) if not banner_list_data: print(鈥?/span>鏌ヨ浜嗘暟鎹簱鈥?/span>) banner_query = models.Banner.objects.filter(is_show=True, is_delete=False).order_by(鈥?/span>-orders鈥?/span>) banner_list_data = serializers.BannerModelSerializer(banner_query, many=True).data # 寤虹珛鎺ュ彛缂撳瓨 cache.set(鈥?/span>api_banner_list_data鈥?/span>, banner_list_data) return Response(banner_list_data)
涓嶈蛋ListAPIView鐨凴esponse,杩斿洖缁欏墠鍙扮殑鏁版嵁涓嶅甫鍓嶇紑,鎵€浠anner.vue闇€鍔犲墠缂€鎵嶈兘璁块棶:
<template> <div class="banner"> <el-carousel height="520px" :interval="3000" arrow="always"> <!--<el-carousel-item>--> <!--<img src="@/assets/img/banner1.png" alt="">--> <!--</el-carousel-item>--> <!--<el-carousel-item>--> <!--<img src="@/assets/img/banner2.png" alt="">--> <!--</el-carousel-item>--> <!--<el-carousel-item>--> <!--<img src="@/assets/img/banner3.png" alt="">--> <!--</el-carousel-item>--> <el-carousel-item v-for="banner in banner_list" :key="banner.image"> <!--<router-link :to="banner.link">--> <!--<img :src="banner.image" alt="">--> <!--</router-link>--> <a :href="banner.link"> <img :src="$settings.base_url + banner.image" > </a> </el-carousel-item> </el-carousel> </div> </template>
璁块棶閲忚繃澶?缂撳瓨涔熸棤娉曞噺缂撴暟鎹簱鐨勮闂帇鍔?闇€瑕佸€熷姪celery
涓? Celery
瀹樻柟
Celery 瀹樼綉锛?span class="md-link">http://www.celeryproject.org/
Celery 瀹樻柟鏂囨。鑻辨枃鐗堬細http://docs.celeryproject.org/en/latest/index.html
Celery 瀹樻柟鏂囨。涓枃鐗堬細http://docs.jinkan.org/docs/celery/
Celery鏋舵瀯
Celery鐨勬灦鏋勭敱涓夐儴鍒嗙粍鎴愶紝娑堟伅涓棿浠讹紙message broker锛夈€佷换鍔℃墽琛屽崟鍏冿紙worker锛夊拰 浠诲姟鎵ц缁撴灉瀛樺偍锛坱ask result store锛夌粍鎴愩€?/span>
娑堟伅涓棿浠?/span>
Celery鏈韩涓嶆彁渚涙秷鎭湇鍔★紝浣嗘槸鍙互鏂逛究鐨勫拰绗笁鏂规彁渚涚殑娑堟伅涓棿浠堕泦鎴愩€傚寘鎷紝RabbitMQ, Redis绛夌瓑
浠诲姟鎵ц鍗曞厓
Worker鏄疌elery鎻愪緵鐨勪换鍔℃墽琛岀殑鍗曞厓锛寃orker骞跺彂鐨勮繍琛屽湪鍒嗗竷寮忕殑绯荤粺鑺傜偣涓€?/span>
浠诲姟缁撴灉瀛樺偍
Task result store鐢ㄦ潵瀛樺偍Worker鎵ц鐨勪换鍔$殑缁撴灉锛孋elery鏀寔浠ヤ笉鍚屾柟寮忓瓨鍌ㄤ换鍔$殑缁撴灉锛屽寘鎷珹MQP, redis绛?/span>
浣跨敤鍦烘櫙
寮傛浠诲姟锛氬皢鑰楁椂鎿嶄綔浠诲姟鎻愪氦缁機elery鍘诲紓姝ユ墽琛岋紝姣斿鍙戦€佺煭淇?閭欢銆佹秷鎭帹閫併€侀煶瑙嗛澶勭悊绛夌瓑
瀹氭椂浠诲姟锛氬畾鏃舵墽琛屾煇浠朵簨鎯咃紝姣斿姣忓ぉ鏁版嵁缁熻
Celery鐨勫畨瑁呴厤缃?/span>
pip install celery
娑堟伅涓棿浠讹細RabbitMQ/Redis
app=Celery(鈥樹换鍔″悕鈥? broker=鈥榵xx鈥? backend=鈥榵xx鈥?
鍖呮灦鏋勫皝瑁?/span>
project
鈹溾攢鈹€ celery_task # celery鍖?br /> 鈹? 鈹溾攢鈹€ __init__.py # 鍖呮枃浠?br /> 鈹? 鈹溾攢鈹€ celery.py # celery杩炴帴鍜岄厤缃浉鍏虫枃浠讹紝涓斿悕瀛楀繀椤诲彨celery.py
鈹? 鈹斺攢鈹€ tasks.py # 鎵€鏈変换鍔″嚱鏁?br /> 鈹溾攢鈹€ add_task.py # 娣诲姞浠诲姟
鈹斺攢鈹€ get_result.py # 鑾峰彇缁撴灉
瀹夎: pip install celery
celery.py:
# 1锛夊垱寤篴pp + 浠诲姟 # 2锛夊惎鍔╟elery(app)鏈嶅姟锛?/span> # 闈瀢indows # 鍛戒护锛歝elery worker -A celery_task -l info # windows锛?/span> # pip3 install eventlet # celery worker -A celery_task -l info -P eventlet # 3锛夋坊鍔犱换鍔★細鎵嬪姩娣诲姞锛岃鑷畾涔夋坊鍔犱换鍔$殑鑴氭湰锛屽彸閿墽琛岃剼鏈?/span> # 4锛夎幏鍙栫粨鏋滐細鎵嬪姩鑾峰彇锛岃鑷畾涔夎幏鍙栦换鍔$殑鑴氭湰锛屽彸閿墽琛岃剼鏈?/span>
浠g爜:
from celery import Celery """ broker=瀛樺偍tasks鐨勪粨搴? backend=瀛樺偍results鐨勪粨搴? include=[浠诲姟鏂囦欢浠琞 """ broker = 鈥?/span>redis://127.0.0.1:6379/11鈥?/span> backend = 鈥?/span>redis://127.0.0.1:6379/12鈥?/span> include = [鈥?/span>celery_task_1.task1鈥?/span>, 鈥?/span>celery_task_1.task2鈥?/span>] app = Celery(broker=broker, backend=backend, include=include) # 鍚姩celery鏈嶅姟鐨勫懡浠?/span>锛?/span> # 鍓嶆彁锛氫竴瀹氳杩涘叆celery_task鎵€灞炵殑鏂囦欢澶?涓婁竴灞? # celery worker -A celery_task_1 -l info -P eventlet
鍩烘湰浣跨敤(鍙啓澶氫釜task鏂囦欢,涔熷彲鎶婂涓嚱鏁板啓鍦ㄤ竴涓猼ask.py鏂囦欢涓?:
tasks.py
from .celery import app import time, random # 浠诲姟灏辨槸涓€涓釜鐨勫姛鑳藉嚱鏁帮紝鍔熻兘鍑芥暟鐨勮繑鍥炲€煎氨鏄换鍔$殑鎵ц缁撴灉 @app.task def add(n, m): res = n + m # 妯℃嫙涓嶅浐瀹氳€楁椂鎿嶄綔 time.sleep(random.randint(1, 5)) print(res) return res
add_task.py:
# 鎵嬪姩娣诲姞浠诲姟鐨勬枃浠讹紝璇ユ枃浠朵笉鏄繀椤荤殑(鍙互鑷姩娣诲姞浠诲姟)
# 璇ユ枃浠朵篃涓嶅睘浜?celery task 鍖呯殑涓€閮ㄥ垎锛屽氨鏄敤鏉ュ疄鐜版墜鍔ㄦ坊鍔犱换鍔$殑
# 灏哸dd娣诲姞鍒癰roker浠撳簱锛宑elery浼氬幓寮傛鎵ц
from celery_task import tasks # 娣诲姞绔嬪嵆鎵ц浠诲姟 t1 = tasks.add.delay(10, 20) t2 = tasks.low.delay(100, 50) print(t1.id) # 娣诲姞寤惰繜浠诲姟 from datetime import datetime, timedelta def eta_second(second): ctime = datetime.now() utc_ctime = datetime.utcfromtimestamp(ctime.timestamp()) time_delay = timedelta(seconds=second) return utc_ctime + time_delay tasks.low.apply_async(args=(200, 50), eta=eta_second(10))
get_result.py:
from celery_task_1.celery import app from celery.result import AsyncResult id = 鈥?/span>4e249f2d-559a-4a3e-8b43-d498b3d6355e鈥?/span> if __name__ == 鈥?/span>__main__鈥?/span>: async = AsyncResult(id=id, app=app) if async.successful(): result = async.get() print(result) elif async.failed(): print(鈥?/span>浠诲姟澶辫触鈥?/span>) elif async.status == 鈥?/span>PENDING鈥?/span>: print(鈥?/span>浠诲姟绛夊緟涓鎵ц鈥?/span>) elif async.status == 鈥?/span>RETRY鈥?/span>: print(鈥?/span>浠诲姟寮傚父鍚庢鍦ㄩ噸璇?/span>鈥?/span>) elif async.status == 鈥?/span>STARTED鈥?/span>: print(鈥?/span>浠诲姟宸茬粡寮€濮嬭鎵ц鈥?/span>)
鑷姩娣诲姞(娌℃湁add_task.py鏂囦欢):
celery.py
from celery import Celery broker = 鈥?/span>redis://127.0.0.1:6379/11鈥?/span> backend = 鈥?/span>redis://127.0.0.1:6379/12鈥?/span> include = [鈥?/span>celery_task.tasks鈥?/span>,] app = Celery(broker=broker, backend=backend, include=include) # 鍚姩celery鏈嶅姟鐨勫懡浠わ細 # 鍓嶆彁锛氫竴瀹氳杩涘叆celery_task鎵€灞炵殑鏂囦欢澶? # celery worker -A celery_task -l info -P eventlet # 鑷姩娣诲姞浠诲姟 # 鏃跺尯 app.conf.timezone = 鈥?/span>Asia/Shanghai鈥?/span> # 鏄惁浣跨敤UTC app.conf.enable_utc = False # 浠诲姟鐨勫畾鏃堕厤缃?/span> from datetime import timedelta from celery.schedules import crontab app.conf.beat_schedule = { 鈥?/span>low-task鈥?/span>: { 鈥?/span>task鈥?/span>: 鈥?/span>celery_task.tasks.low鈥?/span>, 鈥?/span>schedule鈥?/span>: timedelta(seconds=3), # 鈥榮chedule鈥? crontab(hour=8, day_of_week=1), # 姣忓懆涓€鏃╁叓鐐?/span> 鈥?/span>args鈥?/span>: (300, 150), }, 鈥?/span>my-add-task鈥?/span>: { 鈥?/span>task鈥?/span>: 鈥?/span>celery_task.tasks.add鈥?/span>, 鈥?/span>schedule鈥?/span>: timedelta(seconds=6), 鈥?/span>args鈥?/span>: (300, 150), } } # 鍚姩 娣诲姞浠诲姟 鏈嶅姟鐨勫懡浠?涔熻杩涘叆celery_task鎵€灞炴枃浠跺す # celery beat -A celery_task -l info
tasks.py:
from .celery import app @app.task def add(n, m): res = n + m print(res) return res @app.task def low(n, m): res = n - m print(res) return res
get_result.py鍚屼笂
celery寮傛澶勭悊django浠诲姟(鎶奵elery_task鏀惧湪澶uffy涓?:
celery.py
# 鍚姩django渚濊禆 # 灏哻elery鏈嶅姟妗嗘灦鏀惧湪椤圭洰鏍圭洰褰曚笅 # import sys # sys.path.append(r鈥楥:UsersoldboyDesktopluffyluffyapi鈥? import os, django os.environ.setdefault(鈥?/span>DJANGO_SETTINGS_MODULE鈥?/span>, 鈥?/span>luffyapi.settings.dev鈥?/span>) django.setup() from celery import Celery broker = 鈥?/span>redis://127.0.0.1:6379/11鈥?/span> backend = 鈥?/span>redis://127.0.0.1:6379/12鈥?/span> include = [鈥?/span>celery_task.tasks鈥?/span>,] app = Celery(broker=broker, backend=backend, include=include) # 鍚姩celery鏈嶅姟鐨勫懡浠わ細 # 鍓嶆彁锛氫竴瀹氳杩涘叆celery_task鎵€灞炵殑鏂囦欢澶?/span> # celery worker -A celery_task -l info -P eventlet # 鑷姩娣诲姞浠诲姟 # 鏃跺尯 app.conf.timezone = 鈥?/span>Asia/Shanghai鈥?/span> # 鏄惁浣跨敤UTC app.conf.enable_utc = False # 浠诲姟鐨勫畾鏃堕厤缃?/span> from datetime import timedelta from celery.schedules import crontab app.conf.beat_schedule = { 鈥?/span>django-task鈥?/span>: { 鈥?/span>task鈥?/span>: 鈥?/span>celery_task.tasks.django_task鈥?/span>, 鈥?/span>schedule鈥?/span>: timedelta(seconds=10), # 鈥榮chedule鈥? crontab(hour=8, day_of_week=1), # 姣忓懆涓€鏃╁叓鐐?/span> 鈥?/span>args鈥?/span>: (), }, } # 鍚姩 娣诲姞浠诲姟 鏈嶅姟鐨勫懡浠?/span> # celery beat -A celery_task -l info
tasks.py:
from .celery import app from django.core.cache import cache from apps.home import models, serializers @app.task def django_task(): banner_query = models.Banner.objects.filter(is_show=True, is_delete=False).order_by(鈥?/span>-orders鈥?/span>) banner_list_data = serializers.BannerModelSerializer(banner_query, many=True).data # 寤虹珛鎺ュ彛缂撳瓨 cache.set(鈥?/span>api_banner_list_data鈥?/span>, banner_list_data) return 鈥?/span>杞挱鍥剧紦瀛樻洿鏂板畬姣?/span>鈥?/span>
以上是关于Luffy--------------(鍥?的主要内容,如果未能解决你的问题,请参考以下文章
[kuangbin甯︿綘椋瀅涓撻鍥?鏈€鐭矾缁冧範 F - Wormholes 锛堝垽鏂礋鐜級