12.Ajax 初识-任务管理

Ajax

浏览器向网站发送请求时,URL 和 表单的形式提交,特点: 页面刷新

  • GET
  • POST

Ajax可以实现向后台偷偷发送请求

  • 依赖JQuery
  • 编写Ajax代码

简单示例:

  • task_list.html DOM方法绑定事件
  {% extends 'layout.html' %}

  {% block content %}
    <div class=" container">
      <h1>任务管理</h1>
      <h2>示例1</h2>
      <input type="button" class="btn btn-primary" value="点击" onclick="clickme();" />
    </div>
  {% endblock %}

  {% block js %}
    <script type="text/javascript">
      function clickme() {
        // console.log("点击了按钮");
        $.ajax({
          url:'/task/ajax/',
          // type:"get",
          type:"post",
          data:{
            n1: 123,
            n2: 456
          },
          success: function (res) {
              console.log(res);
          }
        })
      }
    </script>
  {% endblock %}
  • task_list.html jquery 方法绑定事件
  {% extends 'layout.html' %}

  {% block content %}
  <div class=" container">
    <h1>任务管理</h1>
    <h2>示例1</h2>
    <input id="btn1" type="button" class="btn btn-primary" value="点击" />
  </div>
  {% endblock %}

  {% block js %}
  <script type="text/javascript">
    $(function () {
      // 当页面的框架加载完成之后,自动执行
      bindBtnEvent1();
    })
    function bindBtnEvent1() {
      $("#btn1").click(function () {
        $.ajax({
          url: '/task/ajax/',
          type: "post",
          data: {
            n1: 123,
            n2: 456
          },
          success: function (res) {
            console.log(res);
          }
        })
      })
    }
  </script>
  {% endblock %}
  • 视图函数
  # 任务管理 urls.py
  # path('task/list/', task.task_list),
  # path('task/ajax/', task.task_ajax),
  # 前端\django\myweb\blog\views\task.py
  from django.shortcuts import render, redirect
  from django.http import HttpResponse
  from django.views.decorators.csrf import csrf_exempt

  def task_list(request):
      """任务列表"""

      return render(request, 'task_list.html')

  @csrf_exempt    # 免除csrf认证可接收Post请求
  def task_ajax(request):
      """Ajax 测试"""

      print(request.GET)   # <QueryDict: {'n1': ['123'], 'n2': ['456']}>
      print(request.POST)  # <QueryDict: {'n1': ['123'], 'n2': ['456']}>
      return HttpResponse("ajax测试成功!")

Ajax 请求的返回值

  • 一般都会返回JSON格式: 得到字符串 {status: true, data: [1, 2, 3, 4, 5]}

    from django.shortcuts import render, redirect
    from django.http import HttpResponse,JsonResponse
    from django.views.decorators.csrf import csrf_exempt
    import json
    
    def task_list(request):
      """任务列表"""
    
      return render(request, 'task_list.html')
    
    @csrf_exempt    # 免除csrf认证可接收Post请求
    def task_ajax(request):
      """Ajax 测试"""
      # print(request.GET)   # <QueryDict: {'n1': ['123'], 'n2': ['456']}>
      print(request.POST)  # <QueryDict: {'n1': ['123'], 'n2': ['456']}>
    
      data_dict = {"status": True, 'data': [1, 2, 3, 4, 5]}
    
      # json_string = json.dumps(data_dict)
      # return HttpResponse(json_string)
    
      # return HttpResponse(json.dumps(data_dict))
    
      return JsonResponse(data_dict)
  • 使用 dataType: "JSON", 拿到字符json字符串后转换为前端的对象,就可以使用res取得对象的值
    <script type="text/javascript">
      $(function () {
      // 当页面的框架加载完成之后,自动执行
      bindBtnEvent1();
      })
      function bindBtnEvent1() {
      $("#btn1").click(function () {
          $.ajax({
          url: '/task/ajax/',
          type: "post",
          data: {
              n1: 123,
              n2: 456
          },
          dataType: "JSON",
          success: function (res) {
              console.log(res);
              console.log(res.status);
              console.log(res.data);
          }
          })
      })
      }
    </script>

Ajax 示例 提交数据

<div class=" container">
  <h2>示例2-ajax提交数据</h2>
  <input type="text" id="txtUser" placeholder="姓名" />
  <input type="text" id="txtAge" placeholder="年龄" />
  <input id="btn2" type="button" class="btn btn-primary" value="点击" />
</div>

<script type="text/javascript">
  $(function () {
    // 当页面的框架加载完成之后,自动执行
    bindBtnEvent1();
    bindBtnEvent2();
  })
  function bindBtnEvent2() {
    $("#btn2").click(function () {
      $.ajax({
        url: '/task/ajax/',
        type: "post",
        data: {
          name: $("#txtUser").val(),
          age: $("#txtAge").val(),
        },
        dataType: "JSON",
        success: function (res) {
          console.log(res);
          console.log(res.status);
          console.log(res.data);
        }
      })
    })
  }
</script>

Ajax 提交数据-form

<div class=" container">
  <h2>示例3-ajax提交数据-form</h2>
  <form id="form3">
    <input type="text" name="user" placeholder="姓名" />
    <input type="text" name="age" placeholder="年龄" />
    <input type="text" name="email" placeholder="邮箱" />
    <input type="text" name="more" placeholder="介绍" />
    <input id="btn3" type="button" class="btn btn-primary" value="点击" />
  </form>
</div>

<script type="text/javascript">
  $(function () {
    // 当页面的框架加载完成之后,自动执行
    bindBtnEvent1();
    bindBtnEvent2();
    bindBtnEvent3();
  })
  function bindBtnEvent3() {
    $("#btn3").click(function () {
      $.ajax({
        url: '/task/ajax/',
        type: "post",
        data: $("#form3").serialize(),
        dataType: "JSON",
        success: function (res) {
          console.log(res);
          console.log(res.status);
          console.log(res.data);
        }
      })
    })
  }
</script>
print(request.POST)  # <QueryDict: {'user': ['tang'], 'age': ['18'], 'email': ['tang@tang.com'], 'more': ['hahaha']}>

Ajax 案例

  • 前端\django\myweb\blog\models.py 创建表
  # 管理员表
  class Admin(models.Model):
      """管理员"""
      username = models.CharField(verbose_name="用户名", max_length=32, unique=True)
      password = models.CharField(verbose_name="密码", max_length=64)

      def __str__(self):
          return str(self.id) + ":" + str(self.username)

  # 任务管理表
  from django.db import models
  class Task(models.Model):
      """任务"""

      level_choices = (
          (1, "紧急"),
          (2, "重要"),
          (3, "临时"),
      )
      level = models.SmallIntegerField(
          verbose_name="级别", choices=level_choices, default=1)
      title = models.CharField(verbose_name="标题", max_length=64)
      detail = models.TextField(verbose_name="详细信息")
      user = models.ForeignKey(verbose_name="负责人", to=Admin, to_field="username",
                              on_delete=models.SET_NULL, null=True, blank=False)
  • 前端\django\myweb\blog\utils\form.py
  # 任务管理
  class TaskModelForm(BootStrapModelForm):
      class Meta:
          model = Task
          fields = "__all__"
  • 前端\django\myweb\blog\templates\task_list.html
  <div class="panel-body">
    <form id="form_add" class="form-group">
      {% for field in form %}
      <div class="form-group" style="position: relative;margin-bottom: 20px;">
        <label>{{ field.label }}: </label>
        {{ field }}
        <span class="error-msg" style="color: red;position: absolute;"></span>
      </div>
      {% endfor %}
      <div class="form-group">
        <button id="btn_form" type="button" class="btn btn-success"><span class="glyphicon glyphicon-plus"
            aria-hidden="true"></span><strong> 提 交</strong></button>
      </div>
    </form>
  </div>

  <script type="text/javascript">
  $(function () {
      // 当页面的框架加载完成之后,自动执行
      bindBtnEvent1();
      bindBtnEvent2();
      bindBtnEvent3();
      bindBtnAddEvent();
  })

  function bindBtnAddEvent() {
      // $(".error_msg").text("");   点击前错误信息置空
      $(".error_msg").empty(); 
      $("#btn_form").click(function () {
      $.ajax({
          url: '/task/add/',
          type: "post",
          data: $("#form_add").serialize(),
          dataType: "JSON",
          success: function (res) {
          if (res.status) {
              alert("添加成功!");
              // 用JS实现页面的刷新
              location.reload();
          } else {
              $.each(res.error, function (name,data){
                  // console.log(name, data);
                  $("#id_" + name).next().text(data[0])
              })
          }
          }
      })
      })
  }
  </script>
  • 前端\django\myweb\blog\views\task.py
  @csrf_exempt    # 免除csrf认证可接收Post请求
  def task_add(request):
      """ form add 测试"""

      # print(request.POST)  # <QueryDict: {'level': ['1'], 'title': ['代码库清理'], 'detail': ['代码库清理'], 'user': ['tang']}>
      print(request.POST)
      # 对用户发送过来的数据进行校验 (ModelForm进行校验)
      form = TaskModelForm(data=request.POST)
      if form.is_valid():
          form.save()
          data_dict = {"status": True}
          return JsonResponse(data_dict)

      # print(type(form.errors))   #<class 'django.forms.utils.ErrorDict'>

      # print(form.errors)  # <ul class="errorlist"><li>title<ul class="errorlist"><li>这个字段是必填项。</li></ul></li><li>detail<ul class="errorlist"><li>这个字段是必填项。</li></ul></li></ul>

      # print(form.errors.as_json()) # {"title": [{"message": "\u8fd9\u4e2a\u5b57\u6bb5\u662f\u5fc5\u586b\u9879\u3002", "code": "required"}], "detail": [{"message": "\u8fd9\u4e2a\u5b57\u6bb5\u662f\u5fc5\u586b\u9879\u3002", "code": "required"}]}
      # 可修改修改源码D:\python\Lib\site-packages\django\forms\utils.py  显示中文正常
      # class RenderableErrorMixin(RenderableMixin):
      # def as_json(self, escape_html=False):
      #     return json.dumps(self.get_json_data(escape_html),ensure_ascii=False)

      # print(form.errors.as_text())

      data_dict = {"status": False, 'error': form.errors}

      return JsonResponse(data_dict)
      # return HttpResponse(json.dumps(data_dict, ensure_ascii=False))
print(request.POST)  # <QueryDict: {'level': ['1'], 'title': ['代码库清理'], 'detail': ['代码库清理'], 'user': ['tang']}
  • 前端\django\myweb\blog\views\task.py 增加任务列表
  def task_list(request):
      """任务列表"""

      data_dict = {}
      search_data = request.GET.get('q', "")   # 有值拿值,没值为空
      if search_data:
          data_dict["title__contains"] = search_data

      # print(request.GET.get)

      # 分页函数封装
      # from blog.utils.pagination import Pagination

      queryset = Task.objects.filter(**data_dict).order_by("id")

      # 初始化封装函数
      page_obj = Pagination(request, queryset)

      task_list = page_obj.page_queryset

      # page_string, head_page, end_page = page_obj.html()
      page_string = page_obj.html()

      form = TaskModelForm()

      context = {
          "task_list": task_list,
          "search_data": search_data,
          "page_string": page_string,
          "form": form
      }

      return render(request, 'task_list.html', context)
  • 前端\django\myweb\blog\templates\task_list.html
  <h2><strong>任务列表</strong></h2>
  <div>
      <form method="get" action="/task/list/">
      <div class="input-group">
          <input type="text" class="form-control" placeholder="查询任务标题" name="q" value="{{ search_data }}">
          <span class="input-group-btn">
          <button class="btn btn-primary" type="submit"><span class="glyphicon glyphicon-search"
              aria-hidden="true"></span><strong> 搜索</strong></button>
          </span>
      </div>
      </form>
  </div>
  <div style="margin-top: 20px;">
      <div class="panel panel-default">
      <div class="panel-heading">
          <strong>
          <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> 任务列表
          </strong>
      </div>
      <table class="table table-bordered">
          <thead>
          <tr>
              <th>ID</th>
              <th>标题</th>
              <th>级别</th>
              <th>负责人</th>
              <th>操作</th>
          </tr>
          </thead>
          <tbody>
          {% for iteam in task_list %}
          <tr>
              <th scope="row">{{ iteam.id }}</th>
              <td>{{ iteam.title }}</td>
              <td>{{ iteam.get_level_display }}</td>
              <td>{{ iteam.user.username }}</td>
              <td>
              <a class="btn btn-primary btn-xs" href="/task/{{ iteam.id }}/edit/"> 编辑 </a>
              <a class="btn btn-danger btn-xs" href="/task/del/?nid={{ iteam.id }}"> 删除 </a>
              </td>
          </tr>
          {% endfor %}
          </tbody>
      </table>
      </div>
  </div>
  <nav aria-label="page">
      <ul class="pagination">
      {{ page_string }}
      <form method="get" action="/task/list/">
          <div class="input-group col-sm-2" style="display: inline-block;margin-left: 20px;">
          <span class="input-group-btn">
              <input type="text" class="form-control" placeholder="页面跳转" name="page">
              <button class="btn btn-primary" type="submit">>> 跳转</button>
          </span>
          </div>
      </form>
      </ul>
  </nav>