BBS專案搭建分步過程
阿新 • • 發佈:2022-03-14
BBS專案搭建分步過程
1. 註冊頁面補充完善
# 註冊前端檔案 register.html檔案中補充: // 提交ajax $.ajax({ url: '', type: 'post', data: myFormData, contentType: false, processData: false, success: function (res) { console.log(res) if (res.status == 200) { layer.msg(res.msg, {icon:1}, function () { location.href = res.url; }) } else { layer.msg(res.msg,); } } }) }) </script> </body> </html> # views.py中補充: from django.http import JsonResponse from app01 import models # 1.註冊功能 def register(request): # 後端一定要對引數進行驗證 if request.method == 'POST': # 返回的是json格式的資料 back_dic = {'status': 200, 'msg': '註冊成功', 'data': {}} # 1.1. 接收引數 username = request.POST.get('username') password = request.POST.get('password') re_password = request.POST.get('re_password') email = request.POST.get('email') img = request.POST.get('img') # 1.2. 驗證引數, 先驗證不正確的引數 if not username: ''' 響應狀態碼 業務狀態碼 財務相關的業務,使用者相關的,訂單相關的 1001 2001 30 ''' back_dic['status'] = 1001 back_dic['msg'] = '使用者名稱必須填寫' return JsonResponse(back_dic) if password != re_password: back_dic['status'] = 1002 back_dic['msg'] = '兩次密碼不一致' return JsonResponse(back_dic) # 驗證使用者名稱是否存在 res = models.UserInfo.objects.filter(username=username).first() if res: back_dic['status'] = 1003 back_dic['msg'] = '使用者名稱已經存在' return JsonResponse(back_dic) # 1.3. 處理正確的業務邏輯 data_dic = {} if img != 'undefined': data_dic['avatar'] = img # 處理密碼 import hashlib from django.conf import settings m = hashlib.md5() password = password + settings.SECRET_KEY m.update(password.encode('utf8')) password = m.hexdigest() data_dic['username'] = username data_dic['password'] = password data_dic['email'] = email # 1.4. 資料入庫 models.UserInfo.objects.create(**data_dic) # 傳入所有獲取的資料 # 1.5. 返回資料 back_dic['url'] = '/login/' return JsonResponse(back_dic) return render(request, 'register.html')
2. 登入頁面搭建
# views.py中寫入登入以及驗證碼功能: # 2. 登入 def login(request): return render(request, 'login.html') # 3. 生成驗證碼 """ 圖片相關的模組 pip3 install pillow """ from PIL import Image, ImageDraw, ImageFont """ Image:生成圖片 ImageDraw:能夠在圖片上亂塗亂畫 ImageFont:控制字型樣式 """ from io import BytesIO, StringIO """ 記憶體管理器模組 BytesIO:臨時幫你儲存資料 返回的時候資料是二進位制 StringIO:臨時幫你儲存資料 返回的時候資料是字串 """ import random def get_random(): # (100, 100, 100) return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) def get_code(request): # 寫圖片驗證碼 img_obj = Image.new('RGB', (430, 35), get_random()) img_draw = ImageDraw.Draw(img_obj) # 產生一個畫筆物件 img_font = ImageFont.truetype('static/font/font.ttf', 30) # 字型樣式 大小 字型檔案可自行百度下載 # 隨機驗證碼 五位數的隨機驗證碼 數字 小寫字母 大寫字母 code = '' for i in range(4): random_upper = chr(random.randint(65, 90)) random_lower = chr(random.randint(97, 122)) random_int = str(random.randint(0, 9)) # 從上面三個裡面隨機選擇一個 tmp = random.choice([random_lower, random_upper, random_int]) # 將產生的隨機字串寫入到圖片上 """ 為什麼一個個寫而不是生成好了之後再寫 因為一個個寫能夠控制每個字型的間隙 而生成好之後再寫的話 間隙就沒法控制了 """ img_draw.text((i * 60 + 60, -2), tmp, get_random(), img_font) # 拼接隨機字串 code += tmp print(code) # 隨機驗證碼在登陸的檢視函式裡面需要用到 要比對 所以要找地方存起來並且其他檢視函式也能拿到 request.session['code'] = code # request.session['code'] = code io_obj = BytesIO() img_obj.save(io_obj, 'png') return HttpResponse(io_obj.getvalue()) # 新建login.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <h1 class="text-center">登入頁面</h1> <div class="col-md-8 col-md-offset-2"> <form action=""> <div class="form-group"> <label for="username">使用者名稱</label> <input type="text" id="username" class="form-control"> </div> <div class="form-group"> <label for="username">密碼</label> <input type="password" id="password" class="form-control"> </div> <div class="form-group"> <label for="myfile"> 驗證碼 </label> <div class="row"> <div class="col-md-6"> <input type="text" class="form-control" id="get_code"> </div> <div class="col-md-6"> <img src="/get_code/" id="re_code" alt="" style="width: 445px; height: 35px;"> </div> </div> </div> <input type="button" class="btn btn-success btn-block" value="登入"> </form> </div> </div> </div> </body> </html> # 路由不要忘了: # 登入頁面 url(r'^login/', views.login), # 生成驗證碼 url(r'^get_code/', views.get_code),
3. 登入後端邏輯的實現
import hashlib from django.conf import settings # 封裝密碼處理功能 def get_pwd(password): m = hashlib.md5() password = password + settings.SECRET_KEY m.update(password.encode('utf-8')) return m.hexdigest() # 補充登入具體功能: # 2. 登入 def login(request): if request.method == 'POST': # 定義返回資料的格式 back_dic = {'status': 200, 'msg': '登入成功', } # 接收引數 username = request.POST.get('username') password = request.POST.get('password') code = request.POST.get('code') # 驗證引數 if code.upper() != request.session.get('code').upper(): # .upper() 轉大寫 不區分大小寫了 back_dic['status'] = 1004 back_dic['msg'] = '驗證碼不正確' return JsonResponse(back_dic) if not username: back_dic['status'] = 1005 back_dic['msg'] = '使用者名稱必須填寫' return JsonResponse(back_dic) # 登入邏輯 password = get_pwd(password) # 獲取加密之後的密碼 # res = models.UserInfo.objects.filter(username=username, password=password).first() '''防止撞庫 同時查詢使用者名稱和密碼 不要只匹配一項就返回結果給使用者''' res = models.UserInfo.objects.filter(username=username, password=password).first() if not res: back_dic['status'] = 1006 back_dic['msg'] = '使用者名稱或者密碼不正確' return JsonResponse(back_dic) # 記錄使用者資訊的 request.session['username'] = username request.session['id'] = res.id back_dic['url'] = '/home/' return JsonResponse(back_dic) return render(request, 'login.html') # 在login.html中 新增資料提交: """ 引入標籤不要忘了: <script src="/static/layer-v3.5.1/layer/layer.js"></script> """ """body標籤內新增script標籤繫結事件:""" <script> // 更換驗證碼 $("#re_code").click(function () { {#var old_code = $('#re_code').attr('src');#} var old_code = $(this).attr('src'); {#$('#re_code').attr('src', old_code);#} $(this).attr('src', old_code); }) $('.btn').click(function () { var username = $('#username').val(); var password = $('#password').val(); var code = $('#get_code').val(); // 驗證引數 if (!username) { layer.msg('使用者名稱必須填寫'); return } if (!password) { layer.msg('密碼必須填寫'); return; } if (!code) { layer.msg('驗證碼必須填寫'); return; } var data = {'username': username, 'password': password, 'code': code} // 提交ajax 請求 $.ajax({ url: '', type: 'post', data: data, // 引數過多時 單獨定義變數儲存 success: function (res) { console.log(res); // 檢視後端返回的資料, if (res.status == 200) { layer.msg(res.msg, {}, function () { location.href = res.url; }) } else { layer.msg(res.msg) } } }) }) </script>
4. 首頁建立
# 路由:
# 首頁
url(r'^home/', views.home),
# views.py補充首頁功能:
# 4. 首頁
def home(request):
return render(request, 'home.html', locals())
# 新建home.html檔案 使用bootstrap的導航條樣式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/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="#">py20BBS</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="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Dropdown <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.session.username %}
<li><a href="#">{{ request.session.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">
<li><a href="#" data-toggle="modal" data-target=".bs-example-modal-lg">修改密碼</a></li>
<li><a href="#">後臺管理</a></li>
<li><a href="/logout/">退出系統</a></li>
</ul>
</li>
{% else %}
<li><a href="/register/">註冊</a></li>
<li><a href="/login/">登入</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
<div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="row">
<h1 class="text-center">修改密碼</h1>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<label for="old_pwd">
原密碼:
</label>
<input type="text" id="old_pwd" class="form-control">
</div>
<div class="form-group">
<label for="new_pwd">
新密碼:
</label>
<input type="text" id="new_pwd" class="form-control">
</div>
<div class="form-group">
<label for="re_pwd">確認密碼:</label>
<input type="text" id="re_pwd" class="form-control">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary set_pwd">提交</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- /.container-fluid -->
</nav>
</body>
</html>
5. 退出系統及修改密碼功能的實現
# html檔案內容在第4點 home.html檔案中
# 新增路由:
# 退出系統
url(r'^logout/', views.logout),
# 修改密碼
url(r'^set_pwd/', views.set_pwd),
# views.py補充功能:
# 5. 退出系統
def logout(request):
request.session.flush()
return redirect('/login/')
# 6. 修改密碼
def set_pwd(request):
if request.method == 'POST':
# 返回的是json格式的資料
back_dic = {'status': 200, 'msg': '修改成功', 'data': {}}
# 1. 接收引數
old_pwd = request.POST.get('old_pwd')
new_pwd = request.POST.get('new_pwd')
re_pwd = request.POST.get('re_pwd')
# 驗證引數
if not old_pwd:
back_dic['status'] = 1008
back_dic['msg'] = '原密碼必須填寫'
return JsonResponse(back_dic)
if re_pwd != new_pwd:
back_dic['status'] = 1009
back_dic['msg'] = '兩次密碼不一致'
return JsonResponse(back_dic)
# 修改密碼
password = get_pwd(new_pwd) # 獲取加密之後的密碼
models.UserInfo.objects.filter(pk=request.session.get('id')).update(password=password)
return JsonResponse(back_dic)
# html檔案內容寫在第4點home.html檔案中:
<script>
$('.set_pwd').click(function () {
var old_pwd = $('#old_pwd').val();
var new_pwd = $('#new_pwd').val();
var re_pwd = $('#re_pwd').val();
// 驗證引數
if (!old_pwd) {
layer.msg('原密碼必須填寫');
return
}
if (!new_pwd) {
layer.msg('新密碼必須填寫');
return;
}
if (!re_pwd) {
layer.msg('確認必須填寫');
return;
}
var data = {'old_pwd': old_pwd, 'new_pwd': new_pwd, 're_pwd': re_pwd}
// 提交ajax 請求
$.ajax({
url: '/set_pwd/',
type: 'post',
data: data,
success: function (res) {
console.log(res); // 檢視後端返回的資料,
if (res.status == 200) {
layer.msg(res.msg, {}, function () {
location.reload();
})
} else {
layer.msg(res.msg)
}
}
})
})
</script>