一、Web開發與django的Ajax
(一)Ajax介紹–gogle公司
Ajax,異步的js和xml
普通提交:會攜帶整個頁面進行提交,最明顯的特徵是需要刷新頁面,頁面重置。很多靜態資源是不需要刷新的,刷新的時候可能阻塞整個服務。
缺點:
- 用戶體驗差
- 請求內容和響應內容冗餘
爲解決上述問題,ajax就出現了
- ajax能夠發送局部的請求,頁面整體不刷新,可進行局部刷新
- ajax可以發送一個異步請求,請求的過程中不會阻塞整個服務
ajax需要使用js語法編寫,原生的js比較複雜,因爲各種瀏覽器都對ajax的兼容不一致,使用js編寫ajax,首先需要完成各個瀏覽器對js的實例創建。
我們使用jq封裝過的ajax。
(二)Ajax請求
1.導包jq
2.Ajax完成一個get請求
Ajax的基本結構
<script>
$("#check_value").click(
function () {
username=$("#username").val(); // 獲取用戶名的值
password=$("#password").val(); // 獲取密碼的值
$.ajax( // 發起一個ajax請求
{ // ajax請求的數據需要放在一個對象中
url:'', // ajax請求的路徑
type:'', // ajax請求的類型
data:'', // ajax請求的數據,在post請求中填寫
success:function (data) { // 請求成功後執行的,data接口返回的數據
},
error:function (error) { //請求報錯之後執行
}
}
);
}
)
</script>
需要兩個視圖
- 完成獲取頁面的功能
- 接收ajax提交的請求,返回響應
路由
視圖
def ajax_get(request):
return render(request,'ajax_get.html')
from django.http import JsonResponse
def ajax_get_data(request):
# 查找數據庫,判斷是否可登錄
result = {'code':10000,'content':''}
data = request.GET
username = data.get('username')
password = data.get('password')
if username=='' or password=='':
result['code'] = 10001
result['content'] = '請求參數爲空'
else:
user = User.objects.filter(name=username,password=setPassword(password)).first()
if user:
result['code'] = 10000
result['content'] = '用戶可登錄'
else:
result['code'] = 10002
result['content'] = '用戶名或密碼錯誤'
# 返回一個json對象
return JsonResponse(result) # 默認情況下,JsonResponse的傳入參數是個字典類型
# return HttpResponse('這是ajax提交數據')
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajaxget請求</title>
<script src="/static/js/jquery-1.8.3.min.js"></script>
</head>
<body>
<form action="">
用戶名:<input id="username" type="text" name="username"><br>
密碼:<input id="password" type="password" name="password"><br>
<input id="check_value" type="button" value="提交">
</form>
<script>
$("#check_value").click(
function () {
username=$("#username").val(); // 獲取用戶名的值
password=$("#password").val(); // 獲取密碼的值
url = '/ajax_get_data/?username='+username+'&password='+password;
$.ajax( // 發起一個ajax請求
{ // ajax請求的數據需要放在一個對象中
url:url, // ajax請求的路徑
type:'get', // ajax請求的類型
data:'', // ajax請求的數據,在post請求中填寫
success:function (data) { // 請求成功後執行的,data接口返回的數據
console.log(data);
console.log(data['content']);
},
error:function (error) { //請求報錯之後執行
}
}
);
}
)
</script>
</body>
</html>
success
error
總結
ajax發送一個get請求
需要兩個視圖:
- 一個提供頁面(處理第一個get請求)
- 返回一個有表單,有ajax請求的頁面
- 另一個接收ajax請求,處理請求,返回響應
- 返回響應 JsonResponse對象
3.Ajax完成一個post請求
ajax_post請求跟get請求一樣,需要兩個視圖。
因爲是一個post請求,所以需要解決CRSF問題。
不同的地方:
- get請求拼接路徑和參數 url = ‘/ajax_get_data/?username=’+username+’&password=’+password;
- get請求的type:‘get’
- post請求的路徑 url=’/ajax_post_data/’;
- post請求的type:‘post’
- 需要構造數據字典,注意要將csrf加進去 ‘csrfmiddlewaretoken’:’{{ csrf_token }}’
路由
視圖
def ajax_post(request):
return render(request,'ajax_post.html')
def ajax_post_data(request):
# 註冊
result={'code':10000,'content':''}
username=request.POST.get('username')
password=request.POST.get('password')
if username=='' or password=='':
result['code'] = 10001
result['content'] = '請補全數據'
else:
user = User()
user.name = username
user.password = setPassword(password)
try:
user.save()
result['content'] = '註冊成功'
except:
result['code'] = 10002
result['content'] = '註冊失敗'
return JsonResponse(result)
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AjaxPost</title>
<script src="/static/js/jquery-1.8.3.min.js"></script>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用戶名:<input id="username" type="text" name="username"><br>
密碼:<input id="password" type="password" name="password"><br>
<input id="check_value" type="button" value="提交">
</form>
<script>
$('#check_value').click(
function () {
username=$('#username').val();
password=$('#password').val();
url='/ajax_post_data/';
// 構造一個數據字典
send_data={
'username':username,
'password':password,
'csrfmiddlewaretoken':'{{ csrf_token }}'
};
$.ajax(
{
url:url,
type:"post",
data:send_data,
success:function (data) {
console.log(data)
},
error:function (error) {
console.log(error)
}
}
)
}
)
</script>
</body>
</html>
解決編碼問題:
中加入ensure_ascii=False
優化–判斷用戶是否存在
當失去焦點時,判斷用戶是否存在
- 局部刷新ajax
- 提交地址(處理業務的視圖)
- 視圖中,獲取傳遞過來的參數,判斷用戶名是否已存在於數據庫表中
- 不存在,可使用
- 存在,不可使用
- 視圖中,獲取傳遞過來的參數,判斷用戶名是否已存在於數據庫表中
- 模板拿到結果,進行渲染
路由
視圖
def checkusername(request):
result={'code':10000,'content':''}
username=request.GET.get('name')
user=User.objects.filter(name=username).exists()
if user: # 存在
result['code']=10001
result['content']='用戶名已存在'
else:
result['content']='該用戶名可用'
return JsonResponse(result)
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AjaxPost</title>
<script src="/static/js/jquery-1.8.3.min.js"></script>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用戶名:<input id="username" type="text" name="username"><div style="color: red" id="text"></div><br>
密碼:<input id="password" type="password" name="password"><br>
<input id="check_value" type="button" value="提交">
</form>
<script>
$('#username').blur(
function () {
username = $('#username').val();
url='/checkusername/?name='+username;
$.ajax(
{
url:url ,
type:'get',
data:'',
success:function (data) {
$('#text').text(data.content)
},
error:function (error) {
$('#text').text(error)
}
}
)
}
);
$('#check_value').click(
function () {
username=$('#username').val();
password=$('#password').val();
url='/ajax_post_data/';
// 構造一個數據字典
send_data={
'username':username,
'password':password,
'csrfmiddlewaretoken':'{{ csrf_token }}'
};
$.ajax(
{
url:url,
type:"post",
data:send_data,
success:function (data) {
console.log(data);
console.log(data.content)
},
error:function (error) {
console.log(error)
}
}
)
}
)
</script>
</body>
</html>
注意:
模板進行url拼接時,使用的是url=’/checkusername/?name=’+username;
參數名爲name
這時視圖中獲取GET請求參數時,需要使用name作爲參數名獲取,即username=request.GET.get(‘name’)
這兩處是需要對應的
二、cookie和session
由於http請求是無狀態的,無法記錄身份,所以需要一種機制能夠長期的記錄身份,最早出現的就是cookie。
cookie:是由服務器下發給用戶的,保存在用戶的瀏覽器上,用於校驗身份的數據,cookie的工作機制就像上面說的通關文牒。
-
用戶第一次請求服務器
服務器驗證用戶的用戶名,密碼,下發cookie
-
用戶第二次攜帶cookie請求服務器
服務器根據用戶攜帶的cookie確定用戶的身份
(一)cookie
優點:
根本上解決了用戶持續訪問的問題
缺點:
由於cookie是保存在用戶本地的,所以會導致一些安全問題,cookie可以被修改,還可以被模仿
1.根據登錄流程認識cookie
- 用戶提供用戶名,密碼進行登錄
- 服務器接收用戶名,密碼
- 驗證用戶名,密碼
- 存在
- 校驗密碼
- 密碼正確
- 設置cookie,下發cookie
- 登錄成功,跳轉到首頁
- 密碼錯誤
- 返回密碼錯誤
- 密碼正確
- 校驗密碼
- 不存在
- 返回用戶不存在
- 存在
2.cookie的使用
首先完成用戶登錄,跳轉到首頁
視圖
# 登錄,重定向
from django.http import HttpResponseRedirect
def login(request):
if request.method == 'POST':
username=request.POST.get('username')
password=setPassword(request.POST.get('password'))
user = User.objects.filter(name=username,password=password).first()
if user: # 用戶存在,且密碼正確
# 跳轉首頁
return HttpResponseRedirect('/index/')
return render(request,'login.html',locals())
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
用戶名:<input type="text" name="username"><br>
密碼:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
路由
cookie的設置
修改視圖
# 登錄,重定向
from django.http import HttpResponseRedirect
def login(request):
if request.method == 'POST':
username=request.POST.get('username')
password=setPassword(request.POST.get('password'))
user = User.objects.filter(name=username,password=password).first()
if user: # 用戶存在,且密碼正確
# 跳轉首頁
response = HttpResponseRedirect('/index/')
response.set_cookie('name','admin')
response.set_cookie('password','123123')
return response
return render(request,'login.html',locals())
cookie設置參數
key cookie的鍵
value cookie的值
max_age=None cookie存在的時間,有效時間
expires=None cookie的超時時間,跟max_age 衝突,兩者二選一
path=’/’ cookie起作用的範圍,默認是當前網頁
domain=None cookie起作用的域名
secure=False 如果爲True使用https傳遞cookie,默認爲False
httponly=False 如果爲True只通過http傳遞cookie
samesite=None 相同的網站(域名)使用cookie
cookie的獲取
利用裝飾器和Cookie,實現登錄攔截
編寫loginVaild裝飾器
# 登錄攔截裝飾器
def loginVaild(fun):
def inner(request,*args,**kwargs):
username=request.COOKIES.get('name')
if username:
return fun(request)
else:
return HttpResponseRedirect('/login/')
return inner
修改index視圖及about視圖
@loginVaild
def about(request):
return render(request,'about.html')
@loginVaild
def index(request):
article = Article.objects.order_by('-date')[:6]
recommend_article = Article.objects.filter(recommend=1)[:7]
click_article = Article.objects.order_by('-click')[:12]
return render(request,'index.html',locals())
cookie的刪除
視圖
# 登出,刪除cookie
def logout(request):
response=HttpResponseRedirect('/login/')
response.delete_cookie('name')
return response
路由
(二)session
session就是爲了解決cookie不安全問題而提出的一種會話機制。
session本身就是一種會話,值一次通信從開始到結束,只有在web開發中,session纔會以會話的機制出現。
web的session是將用戶的信息存在服務器上面的一種web身份校驗技術。session需要結合cookie使用,需要通過cookie下發一個id(session_id),然後將用戶的具體信息保存在數據庫中。
cookie和session的區別
- cookie放在本地,session放在服務器上面,通常是在數據庫當中
- 校驗cookie速度快,但安全性不高
- 校驗session速度慢,但安全性較高
1.session的操作
session的創建
session的獲取
session對象在django當中以一個類字典對象出現,我們可以使用字段的方法對其進行操作。
session的刪除
博客項目修改頁面
項目源碼
持續更新
修改文章頁
視圖
路由
模板
完成一個完整的登錄效果
項目源碼
持續更新
進入虛擬環境,創建項目,創建app子應用
配置:
- 註冊子應用
- 創建templates和static目錄
- 配置templates和static
- 配置數據庫
創建模型
class LoginUser(models.Model):
email = models.EmailField()
password = models.CharField(max_length=32)
username = models.CharField(max_length=32,null=True,blank=True)
# null針對數據庫,True表示可以爲空,即在數據庫的存儲中可以爲空
# blank 針對表單,表示在表單中該字段可以不填,但對數據庫沒有影響
phone_number = models.CharField(max_length=11,null=True,blank=True)
photo = models.ImageField(upload_to='images',null=True,blank=True)
age = models.IntegerField(null=True,blank=True)
gender = models.CharField(max_length=4,null=True,blank=True)
address = models.TextField(null=True,blank=True)
數據遷移
數據庫配置
pycharm默認沒有安裝sqlite驅動
需要下載
安裝缺少的驅動文件
將他們移除
再次拖入
查看數據庫