Django專案-個人網站之登入註冊模組
阿新 • • 發佈:2019-01-06
Django專案之個人網站
感興趣的可以fork或star一下
功能模組一:登入/註冊
一、說明
功能:使用者名稱、密碼、驗證碼輸入、頭像上傳
技術:檔案上傳、驗證碼、密碼加密、會話技術
二、介面
1、登入
2、註冊
三、程式碼
1、前端(T)
1.1 base.html
{# 父模板base.html#}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" >
{# 響應式web設計,自適應瀏覽器大小#}
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="save" content="history">
{% block title %}
<title>首頁</title>
{% endblock %}
{% block link %}
{% endblock %}
<link href="{% static 'SitesApp/css/reset.css' %}" rel="stylesheet">
<link href="{% static 'SitesApp/css/sitesAppCss.css' %}" rel="stylesheet">
{# <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">#}
{# <script src="https://cdn.bootcss.com/jquery/1.12.0/jquery.min.js"></script>#}
{# <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>#}
<link href="/static/SitesApp/css/bootstrap.min.css" rel="stylesheet">
{% block style %}
{% endblock %}
<script src="/static/SitesApp/js/jquery.min.js"></script>
<script src="/static/SitesApp/js/bootstrap.min.js"></script>
{% block script %}
<script type="text/javascript"></script>
{% endblock %}
</head>
<body style="background-color: #E6E6FA;">
<a href="{% url 'sitesApp:vote' 1 %}">hhhhh</a>
<div class="box">
<div class="header">
<ul class="nav nav-pills navbar faq-tabbable">
<li role="presentation" class="active"><a href="{% url 'sitesApp:home' %}">首頁</a></li>
<li role="presentation"><a href="{% url 'sitesApp:vote' 1 %}">投票</a></li>
<li role="presentation"><a href="{% url 'sitesApp:grade' %}">打分</a></li>
<li role="presentation"><a href="{% url 'sitesApp:review' %}">回顧</a></li>
<li role="presentation"><a href="{% url 'sitesApp:blog' %}">部落格</a></li>
<li role="presentation"><a href="{% url 'sitesApp:dataBank' %}">資料</a></li>
<li role="presentation"><a href="{% url 'sitesApp:forum' %}">論壇</a></li>
<li role="presentation"><a href="{% url 'sitesApp:mine' %}">我的</a></li>
<li role="presentation"><a href="{% url 'sitesApp:login' %}">登入</a></li>
<li role="presentation"><a href="{% url 'sitesApp:register' %}">註冊</a></li>
</ul>
</div>
<div class="time" >
<span id="mytime"></span>
</div>
<div class="content" style="position: relative;">
{% block content %}
這傢伙很懶,還沒開始開發...~_~
{% endblock %}
</div>
<div class="footer">
{% block footer %}
開發者 LDC
{% endblock %}
</div>
</div>
<script type="text/javascript">
$(function ($) {
{# 導航欄按鈕渲染#}
$(".faq-tabbable").find("li").each(function () {
var a = $(this).find("a:first")[0];
if ($(a).attr("href") === location.pathname) {
$(this).addClass("active");
} else {
$(this).removeClass("active");
}
});
});
{#實時顯示時間#}
function showTime(){
nowtime=new Date();
year=nowtime.getFullYear();
month=nowtime.getMonth()+1;
date=nowtime.getDate();
document.getElementById("mytime").innerText=year+"年"+month+"月"+date+" "+nowtime.toLocaleTimeString();
}
<!--定時重新整理時間-->
setInterval("showTime()",1000);
</script>
</body>
</html>
1.2 login.html
{% extends 'SitesApp/base.html' %}
{% block title %}
<title>登入</title>
{% endblock %}
{% block content %}
{# 檔案上傳、驗證碼、密碼加密、會話技術#}
<form id="formLogin" method="post" action="{% url 'sitesApp:login' %}"
onkeydown="if(event.keyCode==13) return focusNextInput(this);">
{% csrf_token %}
<div class="login">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">使用者名稱</span>
<input type="text" class="form-control" placeholder="Username" aria-describedby="basic-addon1"
name="uname" onkeyup="if(event.keyCode==13) focusNextInput(this);">
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">密 碼</span>
<input type="password" class="form-control" placeholder="Password" aria-describedby="basic-addon1"
name="upwd" onkeyup="if(event.keyCode==13) focusNextInput(this);">
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">驗證碼</span>
<input type="text" class="form-control" placeholder="Auth code" aria-describedby="basic-addon1"
name="vcode" onkeyup="if(event.keyCode==13) focusNextInput(this);">
</div>
<div class="vcode">
<img src="/app/getvcode/" id="vcode">
</div>
<input id="submit" type="submit" class="loginBtn" value="登 錄">
</div>
</form>
{% endblock %}
{% block script %}
<script src="/static/SitesApp/js/jquery-form.js"></script>
<script type="text/javascript">
$(function () {
{# 驗證碼點選時生成隨機的路由請求#}
$('#vcode').click(function () {
$(this).attr('src', "/app/getvcode" + Math.random())
})
});
{# 表單提交後,處理伺服器返回的資料#}
$(document).ready(function () {
$("#formLogin").ajaxForm(function (data) {
{# alert("post success." + data);#}
data = $.parseJSON(data);
if (data['status'] == '1') {
{# alert('登入成功');#}
{# 跳轉到我的主頁 #}
window.location.href = "{% url 'sitesApp:mine' %}";
} else {
alert(data['ret']);
}
});
});
//jQuery實現在一個輸入框按回車鍵後游標跳到下一個輸入框
function focusNextInput(thisInput) {
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
// 如果是最後一個,則焦點回到第一個
if (i == (inputs.length - 1)) {
inputs[0].focus();
break;
} else if (thisInput == inputs[i]) {
inputs[i + 1].focus();
break;
}
}
return false;
}
</script>
{% endblock %}
1.3 register.html
{% extends 'SitesApp/base.html' %}
{% block title %}
<title>註冊</title>
{% endblock %}
{% block content %}
{# 檔案上傳、驗證碼、密碼加密、會話技術#}
{# enctype="multipart/form-data" 上傳支援 #}
<form id="formLogin" method="post" action="{% url 'sitesApp:register' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="login" style="height: 380px">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">使用者名稱</span>
<input type="text" class="form-control" placeholder="Username" aria-describedby="basic-addon1"
id="uname" name="uname" >
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">暱 稱</span>
<input type="text" class="form-control" placeholder="Nickname" aria-describedby="basic-addon1"
id="unick" name="unick" >
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">密 碼</span>
<input type="password" class="form-control" placeholder="Password" aria-describedby="basic-addon1"
id="upwd" name="upwd" >
</div>
<div class="input-group">
{# 用於上傳頭像的表單控制元件 #}
<span class="input-group-addon" id="basic-addon1">頭 像</span>
<input type="file" class="form-control" aria-describedby="basic-addon1" style="height: 37px;"
id="uicon" name="uicon" onchange="check()">
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">驗證碼</span>
<input type="text" class="form-control" placeholder="Auth code" aria-describedby="basic-addon1"
id="vcod" name="vcode" onchange="check()">
</div>
<div class="vcode" style="margin: 0;height: 65px;">
<img src="/app/getvcode/" id="vcode">
</div>
<input type="submit" class="loginBtn" value="注 冊">
</div>
</form>
{% endblock %}
{% block script %}
<script src="/static/SitesApp/js/jquery-form.js"></script>
<script type="text/javascript">
{# 驗證碼點選事件 #}
$(function () {
$('#vcode').click(function () {
$(this).attr('src', "/app/getvcode" + Math.random())
});
});
{# 表單資料提交後對伺服器返回的資料進行處理#}
$(document).ready(function () {
$("#formLogin").ajaxForm(function (data) {
{# alert("post success." + data['status']);#}
if (data['status'] == '1') {
alert('註冊成功');
window.location.href = "{% url 'sitesApp:login' %}";
} else {
alert("註冊失敗,請檢查輸入資訊!!!");
}
});
});
{# 檢查上傳的檔案是否為圖片#}
function check() {
var icon = document.getElementById("icon").value.toLowerCase().split('.');//以“.”分隔上傳檔案字串
if (icon[icon.length - 1] == 'gif' || icon[icon.length - 1] == 'jpg' || icon[icon.length - 1] == 'bmp'
|| icon[icon.length - 1] == 'png' || icon[icon.length - 1] == 'jpeg')//判斷圖片格式
{
var imagSize = document.getElementById("icon").files[0].size;
{# alert("圖片大小:" + imagSize + "B");#}
if (imagSize < 1024 * 1024 * 3) {
return true;
}
alert("圖片大小在3M以內,您選中的圖片大小為:" + (imagSize / (1024 * 1024)).toFixed(2) + "M");
}
else {
alert('請選擇格式為*.jpg、*.gif、*.bmp、*.png、*.jpeg 的圖片');
}
{# 檔案選擇錯就把原檔案清空#}
var obj = document.getElementById('icon');
obj.outerHTML = obj.outerHTML;
}
</script>
{% endblock %}
2 路由處理(V)
2.1 專案下的總路由
urlpatterns = [
url('^app/',include('SitesApp.urls',namespace='sitesApp'))
]
2.2 子應用下的路由
# 登入
url(r'^login/', views.login, name='login'),
# 註冊
url(r'^register/', views.register, name='register'),
3、檢視函式處理(Views)
3.1 登入
# 登入
def login(request):
if request.method == 'GET':
return render(request, 'SitesApp/login.html')
else:
# 預定義一個最終返回的Response物件(可以動態地為其配置內容,要想勒令客戶端做事情必須要有一個Response物件)
resp = HttpResponse()
respData = {'status': '0', 'ret': '登入失敗,輸入資訊有誤!!!'}
# 獲取使用者輸入的使用者名稱、密碼、驗證碼
uname = request.POST.get('uname', None)
upwd = request.POST.get('upwd', None)
vcode = request.POST.get('vcode', None)
# 校驗驗證碼
# 從session中獲取正確的驗證碼
sessVcode = request.session.get('vcode', None)
# 比較使用者輸入的驗證碼與正確的驗證碼是否匹配
# 事先全部轉換為小寫形式,這樣使用者可以忽略大小寫
if vcode and sessVcode and vcode.lower() == sessVcode.lower():
# 對密碼做訊息摘要
upwd = useMd5(upwd)
# 查詢名稱為uname的使用者
user = User.uManager.filter(uName=uname).first()
if not user:
respData = {'status': '0', 'ret': '使用者不存在!!!'}
# 檢查密碼、驗證碼是否匹配
if user and upwd == user.uPwd :
# # 勒令客戶端(通過cookie)自己將狀態儲存起來,過期時間為60秒
# resp.set_cookie('uname',uname,max_age=60*1)
# # 讓服務端通過session儲存使用者狀態
# 向客戶端端要session其實是要儲存在cookie中的sessionid
# request.session的言下之意是"request.getSessionBySessionid"
# request.session['uname'] = uname
# request.session['upwd'] = upwd
'''
token相當於手動實現的session
session將使用者狀態儲存在django_session的表中
token將使用者狀態儲存在何處完全取決於程式媛自己,例如:User表
但務必使儲存使用者狀態的這張表中有用於作為[id/key/信物]的欄位(該欄位必須唯一),例如:utoken
和session一樣,必須在客戶端的cookie中存一個相同的[id/key/信物],例如:utoken
如何獲取儲存的使用者狀態:先從cookie中拿出utoken,進而查詢User表中utoken為xxx的記錄,就可以拿到uname了
'''
# 將使用者狀態儲存在token中,讓客戶端持有一個token,將該token儲存在某個表中
# 生成令牌/信物
token = str(uuid.uuid4())
# 將該令牌/信物儲存在客戶端的cookie中,過期時間一天
resp.set_cookie('utoken', token,expires=60*60*24)
# 將同樣的信物存一份在服務端的表中
user.uToken = token
try:
user.save()
respData = {'status': '1', 'ret': 'login success!'}
except BaseException as e:
print(e)
respData = {'status': '0', 'ret': '登入失敗,輸入資訊有誤!!!'}
pass
resp.content = json.dumps(respData)
return resp
3.2 註冊
# 註冊
def register(request):
if request.method == 'GET':
return render(request, 'SitesApp/register.html')
else:
# 獲取使用者輸入的使用者名稱、暱稱、密碼、驗證碼、上傳的頭像
uname = request.POST.get('uname', None)
unick = request.POST.get('unick', None)
upwd = request.POST.get('upwd', None)
vcode = request.POST.get('vcode', None)
uip = getUserIP(request)
# 拿到使用者上傳的檔案資料,型別是框架類InMemoryUploadedFile
uiconFile = request.FILES.get('uicon', None)
# <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
print(uname,unick, upwd, vcode, uiconFile, type(uiconFile))
# 手動儲存上傳的檔案
# 自定義檔案位置
# if uiconFile:
# fp = os.path.join(MEDIA_ROOT, 'x-' + uiconFile.name)
# # 寫入檔案
# with open(fp, 'wb') as file:
# # 逐"桶"讀取上傳的檔案資料,並寫入本地檔案
# for buffer in uiconFile.chunks():
# file.write(buffer)
# 校驗驗證碼
# 從session中獲取正確的驗證碼
sessVcode = request.session.get('vcode', None)
# 比較使用者輸入的驗證碼與正確的驗證碼是否匹配
# 事先全部轉換為小寫形式,這樣使用者可以忽略大小寫
if vcode and sessVcode and vcode.lower() == sessVcode.lower():
user = User()
user.uName = uname
user.uNickName = unick
user.uIP = uip
# 對密碼做訊息摘要(目的是避免明文儲存)
user.uPwd = useMd5(upwd)
# 將上傳過來的檔案直接賦值給使用者的ImageField欄位uicon
# 框架會自動將圖片儲存在MEDIA_ROOT中
if uiconFile:
user.uIcon = uiconFile
# 把資料寫進資料庫
try:
user.save()
return JsonResponse({'status': 1, 'ret': 'register success!'})
except BaseException as e:
print(e)
return JsonResponse({'status':0,'ret':'輸入資訊有誤!'})