Django框架(八)--Ajax,Cookie,Session,博客項目修改文章頁(分類),完成完整登錄效果

一、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>

需要兩個視圖

  1. 完成獲取頁面的功能
  2. 接收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請求

需要兩個視圖:

  1. 一個提供頁面(處理第一個get請求)
    • 返回一個有表單,有ajax請求的頁面
  2. 另一個接收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的工作機制就像上面說的通關文牒。

  1. 用戶第一次請求服務器

    服務器驗證用戶的用戶名,密碼,下發cookie

  2. 用戶第二次攜帶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子應用

在這裏插入圖片描述
在這裏插入圖片描述

配置:

  1. 註冊子應用
  2. 創建templates和static目錄
  3. 配置templates和static
  4. 配置數據庫

創建模型

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驅動

需要下載

在這裏插入圖片描述

在這裏插入圖片描述

安裝缺少的驅動文件

在這裏插入圖片描述
將他們移除

在這裏插入圖片描述

再次拖入
在這裏插入圖片描述

查看數據庫
在這裏插入圖片描述

修改頁面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章