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驱动

需要下载

在这里插入图片描述

在这里插入图片描述

安装缺少的驱动文件

在这里插入图片描述
将他们移除

在这里插入图片描述

再次拖入
在这里插入图片描述

查看数据库
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值