BBS階段性測試總要求
django登錄報錯
Error: [WinError 10013] 以一種訪問權限不允許的方式做了一個訪問套接字的嘗試。
原因分析:出現這種情況在Windows中很常見,就是端口被占用
解決措施:這時我們只需改一下端口便可以了
登錄前端頁面(HTML)
# 這次頁面采用的是bookstrip5:Bootstrap 入門 · Bootstrap v5 中文文檔 v5.3 | Bootstrap 中文網 (bootcss.com)
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<style>html,body {height: 100%;}body {display: flex;align-items: center;padding-top: 40px;padding-bottom: 40px;background-color: #f5f5f5;}.form-signin {max-width: 330px;padding: 15px;}.form-, .form-floating:focus-within {z-index: 2;}.form-signin input[type="email"] {margin-bottom: -1px;border-bottom-right-radius: 0;border-bottom-left-radius: 0;}.form-signin input[type="password"] {margin-bottom: 10px;border-top-left-radius: 0;border-top-right-radius: 0;a {color: rgba(1, 4, 12, 0.92);ext-decoration: none;}} </style>
# body部分: <body> <main class="form-signin w-100 m-auto"><div class="text-center"><div class="form-group"><label for="id_avatar"><img class="mb-4 "src="https://tse3-mm.cn.bing.net/th/id/OIP-C.VeJFhbdc95msPtA2RFHHbwAAAA?rs=1&pid=ImgDetMain"alt="" height="80px" width="80px" id="id_img1"style="margin-left: 20px"></label><input type="file" id="id_avatar" class="form-control" accept="image/*" style="display: none"><h1 class="h3 mb-3 fw-normal">糖果愛上我</h1></label></div></div><form id="login_form">{% csrf_token %}<div class="form-floating"><div class="group-group"><label for="id_username">用戶名</label><input type="text" name="username" class="form-control"id="id_username"><span class="pull-right error" style="color: red"> </span></div><div class="form-group"><label for="floatingInput">密碼</label><input type="password" name="password" class="form-control"id="id_password"><span class="pull-right error" style="color: red"> </span></div><div class="form-group"><label for="floatingInput">驗證碼</label><div class="row"><div class="col-md-6"><input type="text" name="code" class="form-control" id="id_code"></div><img src="/get_valid_code/" alt="" class="col-md-6" height="35" id="id_img"></div></div></div></form><div class="w-100 btn btn-lg btn-primary" id="id_submit" style="margin-top: 20px">登錄</div><span class="error" style="color: darkred;margin-left: 10px" id="id_error"></span><p style="color: #888888">您還沒賬號嗎?那我們先注冊一個吧~ <a href="/register/">滴滴</a></p><p class="mt-5 mb-3 text-muted">* 佳祺今天也要加油鴨</p> </main> </body>
驗證碼功能
# 能夠顯示驗證碼圖片,隨機改變驗證碼,點擊圖片就會自己刷新驗證碼
# 視圖層后端,自定義驗證碼,驗證碼用session進行保存,方便后面驗證是否正確:
from django.shortcuts import render, HttpResponse, redirect from PIL import Image, ImageDraw, ImageFont from .utills import get_random_code, get_random_rgb from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout import random, json from io import BytesIOdef get_valid_code(request):height = 38width = 300image_tmp = Image.new('RGB', (300, 38), (255, 255, 255))# 把空圖片放在了畫板上,就可以寫字了draw = ImageDraw.Draw(image_tmp)# 加入字體img_font = ImageFont.truetype('./static/font/ss.TTF', 23)# 驗證碼code_str = get_random_code()print(code_str)# 重要,要保存request.session['code'] = code_strfor i, item in enumerate(code_str):draw.text((30 + i * 50, 3), item, fill=get_random_rgb(), font=img_font) # (x軸,y軸),字,字顏色,字體# 增加難度--->在圖片上畫點for i in range(30):draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_rgb())# 畫弧形x = random.randint(0, width)y = random.randint(0, height)draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_rgb())# 在圖片上劃線for i in range(3):x1 = random.randint(0, width)x2 = random.randint(0, height)y1 = random.randint(0, width)y2 = random.randint(0, height)draw.line((x1, y1, x2, y2), fill=get_random_rgb())# 放在內存中,一旦不用,自動清理內存my_io = BytesIO()image_tmp.save(my_io, 'png')return HttpResponse(my_io.getvalue())
# 講圖片渲染在前端html頁面:
<div class="form-group"><label for="floatingInput">驗證碼</label><div class="row"><div class="col-md-6"><input type="text" name="code" class="form-control" id="id_code"></div><img src="/get_valid_code/" alt="" class="col-md-6" height="35" id="id_img"></div> </div>
# 設置驗證碼id,設置點擊事件,使點擊驗證碼圖片會自己刷新驗證碼:
<script>$('#id_img').click(function () {// img標簽有個特性:只要src變了,就會重新src地址請求拿數據var url = $(this).attr('src') + '?' // /get_valid_code/???console.log(url)$(this).attr('src', url)}) </script>
圖片渲染在前端配置
# 在django中,有兩個額外自己建立的文件包:
media:一般存入其他用戶上傳的圖片等等
static: 一般用于自身寫入的引入樣式,圖片等等? ? ? ?
# 因此,存入的圖片,我們想要渲染在前端頁面,也需配置成靜態文件
# settings.py STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'# 路由 path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),
ajax提交登錄
# 前端把用戶提交的數據發送到后端,設置button點擊事件,用ajax提交數據:
<script> $('#id_submit').click(function () {var serialize_data = $('#login_form').serializeArray()console.log(serialize_data)var data = {}var username = $('[name="username"]').val()var password = $('[name="password"]').val()var code = $('[name="code"]').val()var csrfmiddlewaretoken = $('[name="csrfmiddlewaretoken"]').val()data['username'] = usernamedata['password'] = passworddata['code'] = codedata['csrfmiddlewaretoken'] = csrfmiddlewaretokenconsole.log(data)$.ajax({url: '',method: 'post',data: data,success: function (data) {console.log(data)if (data.code == 100) {location.href = data.url} else {$("#id_error").html(data.msg)}}})}) </script>
# 后端拿到前端數據,先對驗證碼進行對比,然后使用auth模塊直接講用戶名和密碼與數據庫中的進行比較,返回給前端信息,成功便直接跳轉到主頁面:
def login(request):if request.method == 'GET':return render(request, 'login.html')else:username = request.POST.get('username')password = request.POST.get('password')net_code = request.POST.get('code').lower()#code = request.POST.get('code').lower() # 會存在bug# 1 校驗驗證碼,取出老驗證碼,忽略大小寫old_code = request.session.get('code').lower()if code == old_code:# 2 去驗證用戶了---》user = authenticate(username=username, password=password)if user:# 登錄成功--->內部寫session了auth_login(request, user)return JsonResponse({'code': 100, 'msg': '登錄成功', 'url': '/'})else:return JsonResponse({'code': 101, 'msg': '用戶名或密碼錯誤'})else:return JsonResponse({'code': 102, 'msg': '驗證碼錯誤'})