【Django 网页Web开发】20. 实战项目:Ajax实战之订单管理与弹出对话框(13)(保姆级图文)

目录

    • 1. moudle.py数据表设计
    • 2. url.py
    • 3. order.py
    • 4. order_list.html
    • 5. 两种弹出对话框的方式
      • 5.1 新建订单1
      • 5.2 新建订单2
    • 6. 一些不需要填写的自动生成的参数
      • 6.1 订单号
      • 6.2 订单管理员ID
    • 7. 订单删除时的全局变量
    • 8. 订单编辑与订单新建的联系与区别
    • 9. 获取数据的格式思考
    • 总结


欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中

【Django 网页Web开发】20. 实战项目:Ajax实战之订单管理与弹出对话框(13)(保姆级图文)_第1张图片

1. moudle.py数据表设计

class Order(models.Model):
    """ 订单 """
    oid = models.CharField(verbose_name="订单号", max_length=64)
    title = models.CharField(verbose_name="名称", max_length=32)
    price = models.IntegerField(verbose_name="价格")

    status_choices = (
        (1, "待支付"),
        (2, "已支付"),
    )
    status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=1)
    # admin_id
    admin = models.ForeignKey(verbose_name="管理员", to="Admin", on_delete=models.CASCADE)# 级联删除,也就是当删除主表的数据的时候从表中的数据也随着一起删除。

【Django 网页Web开发】20. 实战项目:Ajax实战之订单管理与弹出对话框(13)(保姆级图文)_第2张图片


2. url.py

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

3. order.py

import json
import random
from datetime import datetime
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from app01 import models
from app01.utils.bootstrap import BootStrapModelForm
from app01.utils.pagination import Pagination


class OrderModelForm(BootStrapModelForm):
    class Meta:
        model = models.Order
        # fields = "__all__"
        # fields = [""]
        exclude = ["oid", 'admin']


def order_list(request):
    queryset = models.Order.objects.all().order_by('-id')
    page_object = Pagination(request, queryset)
    form = OrderModelForm()

    context = {
        'form': form,
        "queryset": page_object.page_queryset,  # 分完页的数据
        "page_string": page_object.html()  # 生成页码
    }

    return render(request, 'order_list.html', context)


@csrf_exempt
def order_add(request):
    """ 新建订单(Ajax请求)"""
    form = OrderModelForm(data=request.POST)
    if form.is_valid():
        # 订单号:额外增加一些不是用户输入的值(自己计算出来)
        form.instance.oid = datetime.now().strftime("%Y%m%d%H%M%S") + str(random.randint(1000, 9999))

        # 固定设置管理员ID,去哪里获取?
        form.instance.admin_id = request.session["info"]["id"]

        # 保存到数据库中
        form.save()
        return JsonResponse({"status": True})
    return JsonResponse({"status": False, 'error': form.errors})


def order_delete(request):
    """ 删除订单 """
    uid = request.GET.get('uid')
    exists = models.Order.objects.filter(id=uid).exists()
    if not exists:
        return JsonResponse({"status": False, 'error': "删除失败,数据不存在。"})

    models.Order.objects.filter(id=uid).delete()
    return JsonResponse({"status": True})


def order_detail(request):
    """ 根据ID获取订单详细 """
    # 方式1
    """
    uid = request.GET.get("uid")
    row_object = models.Order.objects.filter(id=uid).first()
    if not row_object:
        return JsonResponse({"status": False, 'error': "数据不存在。"})

    # 从数据库中获取到一个对象 row_object
    result = {
        "status": True,
        "data": {
            "title": row_object.title,
            "price": row_object.price,
            "status": row_object.status,
        }
    }
    return JsonResponse(result)
    """

    # 方式2
    uid = request.GET.get("uid")
    row_dict = models.Order.objects.filter(id=uid).values("title", 'price', 'status').first()
    if not row_dict:
        return JsonResponse({"status": False, 'error': "数据不存在。"})

    # 从数据库中获取到一个对象 row_object
    result = {
        "status": True,
        "data": row_dict
    }
    return JsonResponse(result)


@csrf_exempt
def order_edit(request):
    """ 编辑订单 """
    uid = request.GET.get("uid")
    row_object = models.Order.objects.filter(id=uid).first()
    if not row_object:
        return JsonResponse({"status": False, 'tips': "数据不存在,请刷新重试。"})

    form = OrderModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return JsonResponse({"status": True})

    return JsonResponse({"status": False, 'error': form.errors})

4. order_list.html

layout.html中加入

  • 订单管理
  • 【Django 网页Web开发】20. 实战项目:Ajax实战之订单管理与弹出对话框(13)(保姆级图文)_第3张图片

    {% extends 'layout.html' %}
    
    {% block content %}
        <div class="container">
            <div style="margin-bottom: 10px">
                <input type="button" value="新建订单1" class="btn btn-success" data-toggle="modal" data-target="#myModal">
    
                <input id="btnAdd" type="button" value="新建订单2" class="btn btn-success">
            div>
    
            
            <div class="panel panel-default">
                
                <div class="panel-heading">
                    <span class="glyphicon glyphicon-th-list" aria-hidden="true">span>
                    订单列表
                div>
    
                
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>IDth>
                        <th>订单号th>
                        <th>名称th>
                        <th>价格th>
                        <th>状态th>
                        <th>管理员th>
                        <th>操作th>
                    tr>
                    thead>
                    <tbody>
                    {% for obj in queryset %}
                        <tr uid="{{ obj.id }}">
                            <th>{{ obj.id }}th>
                            <td>{{ obj.oid }}td>
                            <td>{{ obj.title }}td>
                            <td>{{ obj.price }}td>
                            <td>{{ obj.get_status_display }}td>
                            <td>{{ obj.admin.username }}td>
                            <td>
                                <input uid="{{ obj.id }}" type="button" class="btn btn-primary btn-xs btn-edit" value="编辑">
                                <input uid="{{ obj.id }}" class="btn btn-danger btn-xs btn-delete" type="button" value="删除">
                            td>
                        tr>
                    {% endfor %}
    
                    tbody>
                table>
            div>
    
            
            <ul class="pagination">
                {{ page_string }}
            ul>
    
    
        div>
    
        
        <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                                aria-hidden="true">×span>button>
                        <h4 class="modal-title" id="myModalLabel">新建h4>
                    div>
                    <div class="modal-body">
    
                        <form id="formAdd">
                            <div class="clearfix">
                                {% for field in form %}
                                    <div class="col-xs-6">
                                        <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>
                                    div>
                                {% endfor %}
                            div>
                        form>
    
                    div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" data-dismiss="modal">取 消button>
                        <button id="btnSave" type="button" class="btn btn-primary">保 存button>
                    div>
                div>
            div>
        div>
    
        
        <div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
            <div class="modal-dialog" role="document">
    
                <div class="alert alert-danger alert-dismissible fade in" role="alert">
                    <h4>是否确定删除?h4>
                    <p style="margin: 10px 0;"> 删除后,所有关联的相关数据都会被删除。p>
                    <p style="text-align: right;">
                        <button id="btnConfirmDelete" type="button" class="btn btn-danger">确 定button>
                        <button type="button" class="btn btn-default" data-dismiss="modal">取 消button>
                    p>
                div>
    
            div>
        div>
    
    {% endblock %}
    
    
    {% block js %}
        <script type="text/javascript">
            var DELETE_ID;{#删除时的全局变量id#}
            var EDIT_ID;{#编辑时的全局变量id#}
    
            $(function () {
                bindBtnAddEvent();
                bindBtnSaveEvent();
                bindBtnDeleteEvent();
                bindBtnConfirmDeleteEvent();
                bindBtnEditEvent();
            })
    
            function bindBtnAddEvent() {
                $("#btnAdd").click(function () {
                    // 将正在编辑的ID设置为空
                    EDIT_ID = undefined;
    
                    // 清空对话框中的数据
                    $("#formAdd")[0].reset();
    
                    // 设置对话框的标题
                    $("#myModalLabel").text("新建");
    
                    // 点击新建按钮,显示对话框。
                    $('#myModal').modal('show');
                });
            }
    
            function bindBtnSaveEvent() {
                $("#btnSave").click(function () {
    
                    // 清除错误信息
                    $(".error-msg").empty();
    
                    if (EDIT_ID) {
                        // 编辑
                        doEdit();
                    } else {
                        // 添加
                        doAdd();
                    }
    
    
                });
            }
    
            function doEdit() {
                // 向后台发送请求(添加的Ajax请求)
                $.ajax({
                    url: "/order/edit/" + "?uid=" + EDIT_ID,  //  -> /order/edit/?uid=12
                    type: "post",
                    data: $("#formAdd").serialize(),
                    dataType: "JSON",
                    success: function (res) {
                        if (res.status) {
                            // 清空表单  $("#formAdd")是jQuery对象 -> $("#formAdd")[0] DOM对象
                            $("#formAdd")[0].reset();
    
                            // 关闭对话框
                            $('#myModal').modal('hide');
    
                            // 刷新页面
                            location.reload();
    
                        } else {
                            if (res.tips) {
                                alert(res.tips);
                            } else {
                                // 把错误信息显示在对话框中。
                                $.each(res.error, function (name, errorList) {
                                    $("#id_" + name).next().text(errorList[0]);
                                })
                            }
                        }
                    }
                })
            }
    
            function doAdd() {
                // 向后台发送请求(添加的Ajax请求)
                $.ajax({
                    url: "/order/add/",
                    type: "post",
                    data: $("#formAdd").serialize(),
                    dataType: "JSON",
                    success: function (res) {
                        if (res.status) {
    
                            // alert("创建成功");
    
                            // 清空表单  $("#formAdd")是jQuery对象 -> $("#formAdd")[0] DOM对象
                            $("#formAdd")[0].reset();
    
                            // 关闭对话框
                            $('#myModal').modal('hide');
    
                            // 刷新页面
                            location.reload();
    
                        } else {
                            // 把错误信息显示在对话框中。
                            $.each(res.error, function (name, errorList) {
                                $("#id_" + name).next().text(errorList[0]);
                            })
                        }
                    }
                })
            }
    
            function bindBtnDeleteEvent() {
                $(".btn-delete").click(function () {
                    // alert("点击了删除");
                    // 显示删除对话框
                    $("#deleteModal").modal('show');
    
                    // 获取当前行的ID并赋值给全部变量。
                    DELETE_ID = $(this).attr("uid");
                });
            }
    
            function bindBtnConfirmDeleteEvent() {
                $("#btnConfirmDelete").click(function () {
                    $.ajax({
                        url: "/order/delete/",  //    => /order/delete/?uid=123
                        type: "GET",
                        data: {
                            uid: DELETE_ID
                        },
                        dataType: "JSON",
                        success: function (res) {
                            if (res.status) {
                                // 隐藏删除框
                                // $("#deleteModal").modal('hide');
                                // 在页面上将当前一行数据删除(js)
                                // $("tr[uid='" + DELETE_ID + "']").remove();
                                // 要删除的ID制空
                                // DELETE_ID = 0;
                                // 简单的思路:
                                location.reload();
                            } else {
                                // 删除失败
                                alert(res.error);
                            }
                        }
                    })
                });
            }
    
            function bindBtnEditEvent() {
                $(".btn-edit").click(function () {
                    // 清空对话框中的数据
                    $("#formAdd")[0].reset();
                    var uid = $(this).attr("uid");
                    EDIT_ID = uid;
    
                    // 发送Ajax去后端获取当前行的相关数据  /order/detail/?uid=123
                    $.ajax({
                        url: "/order/detail/",
                        type: "get",
                        data: {
                            uid: uid
                        },
                        dataType: "JSON",
                        success: function (res) {
                            if (res.status) {
                                // 将数据赋值到对话框中的标签中。
                                $.each(res.data, function (name, value) {
                                    $("#id_" + name).val(value);
                                })
                                // 修改对话框的标题
                                $("#myModalLabel").text("编辑");
    
                                // 点击编辑,显示对话框
                                $('#myModal').modal('show');
                            } else {
                                alert(res.error);
                            }
                        }
                    })
                });
            }
    
        script>
    {% endblock %}
    
    

    5. 两种弹出对话框的方式

    5.1 新建订单1

    采用bootstrap自带的js实现,需要一个按钮带有如下属性,data-target的值是目标div的id

    data-toggle="modal" data-target="#myModal"
    
        <!-- 新建/编辑 订单(对话框) -->
        <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    

    5.2 新建订单2

    使用自己编写的js调用,不需要给按钮添加特定的属性。但是需要自己使用jq,用官方文档中写好的对应方法,比如说这里显示对话框使用的是.show()的方法

            function bindBtnAddEvent() {
                $("#btnAdd").click(function () {
                    // 将正在编辑的ID设置为空
                    EDIT_ID = undefined;
    
                    // 清空对话框中的数据
                    $("#formAdd")[0].reset();
    
                    // 设置对话框的标题
                    $("#myModalLabel").text("新建");
    
                    // 点击新建按钮,显示对话框。
                    $('#myModal').modal('show');
                });
            }
    

    6. 一些不需要填写的自动生成的参数

    6.1 订单号

    订单号是年月日时间+随机的一段数字

    form.instance.oid = datetime.now().strftime("%Y%m%d%H%M%S") + str(random.randint(1000, 9999))
    

    6.2 订单管理员ID

    我们肯定是登录的情况下才能添加订单,一般情况生成的订单的管理员id就应该是我们这个登录的用户。

    我们在之前把id存入了session中的id中
    在这里插入图片描述

            # 固定设置管理员ID,去哪里获取?
            form.instance.admin_id = request.session["info"]["id"]
    

    注意,数据库中存储的是id,但是我们页面显示的应该是管理员的username
    【Django 网页Web开发】20. 实战项目:Ajax实战之订单管理与弹出对话框(13)(保姆级图文)_第4张图片


    7. 订单删除时的全局变量

    • 我们点击删除时弹窗提示,此时把这一行的id传给全局变量,等我们点击了确定删除后,再根据这个全局变量删除后台数据库的数据。
    • 在确定删除时,location.reload();可以隐藏对话框,清除全局变量,并且已经将删除的ajax请求发送,一种偷懒简便的方法。
            var DELETE_ID;{#删除时的全局变量id#}
            var EDIT_ID;{#编辑时的全局变量id#}
            function bindBtnDeleteEvent() {
                $(".btn-delete").click(function () {
                    // alert("点击了删除");
                    // 显示删除对话框
                    $("#deleteModal").modal('show');
    
                    // 获取当前行的ID并赋值给全部变量。
                    DELETE_ID = $(this).attr("uid");
                });
            }
    function bindBtnConfirmDeleteEvent() {
                $("#btnConfirmDelete").click(function () {
                    $.ajax({
                        url: "/order/delete/",  //    => /order/delete/?uid=123
                        type: "GET",
                        data: {
                            uid: DELETE_ID
                        },
                        dataType: "JSON",
                        success: function (res) {
                            if (res.status) {
                                // 隐藏删除框
                                // $("#deleteModal").modal('hide');
                                // 在页面上将当前一行数据删除(js)
                                // $("tr[uid='" + DELETE_ID + "']").remove();
                                // 要删除的ID制空
                                // DELETE_ID = 0;
                                // 简单的思路 reload 那么一切就都重置了,和上面的注释效果相同:
                                location.reload();
    
                            } else {
                                // 删除失败
                                alert(res.error);
                            }
                        }
                    })
                });
            }
    

    8. 订单编辑与订单新建的联系与区别

    • 其实订单编辑的对话框与订单新建的对话框除了对话框标题不一样样式结构都是一样的,可以复用。

    • 订单编辑需要多一次ajax请求获取后台数据显示在表单中。根据id获取得到当前这一行的数据,显示在对话框中

          function bindBtnEditEvent() {
                $(".btn-edit").click(function () {
                    // 清空对话框中的数据
                    $("#formAdd")[0].reset();
                    var uid = $(this).attr("uid");
                    EDIT_ID = uid;
    
                    // 发送Ajax去后端获取当前行的相关数据  /order/detail/?uid=123
                    $.ajax({
                        url: "/order/detail/",
                        type: "get",
                        data: {
                            uid: uid
                        },
                        dataType: "JSON",
                        success: function (res) {
                            if (res.status) {
                                // 将数据赋值到对话框中的标签中。
                                $.each(res.data, function (name, value) {
                                    $("#id_" + name).val(value);
                                })
                                // 修改对话框的标题
                                $("#myModalLabel").text("编辑");
    
                                // 点击编辑,显示对话框
                                $('#myModal').modal('show');
                            } else {
                                alert(res.error);
                            }
                        }
                    })
                });
            }
    
    • 需要传入当前行id去数据库中找对应的数据,如果有对应的数据才能显示对话框。
    function doEdit() {
                // 向后台发送请求(添加的Ajax请求)
                $.ajax({
                    url: "/order/edit/" + "?uid=" + EDIT_ID,  //  -> /order/edit/?uid=12
                    type: "post",
                    data: $("#formAdd").serialize(),
                    dataType: "JSON",
                    success: function (res) {
                        if (res.status) {
                            // 清空表单  $("#formAdd")是jQuery对象 -> $("#formAdd")[0] DOM对象
                            $("#formAdd")[0].reset();
    
                            // 关闭对话框
                            $('#myModal').modal('hide');
    
                            // 刷新页面
                            location.reload();
    
                        } else {
                            if (res.tips) {
                                alert(res.tips);
                            } else {
                                // 把错误信息显示在对话框中。
                                $.each(res.error, function (name, errorList) {
                                    $("#id_" + name).next().text(errorList[0]);
                                })
                            }
                        }
                    }
                })
            }
    

    9. 获取数据的格式思考

    ajax需要适配字典数据,我们使用filter()得到的是对象,还需要转化为字典

    想要去数据库中获取数据时:对象/字典

    # 对象,当前行的所有数据。
    row_object = models.Order.objects.filter(id=uid).first()
    row_object.id
    row_object.title
    
    # 字典,{"id":1,"title":"xx"}
    row_dict = models.Order.objects.filter(id=uid).values("id","title").first()
    
    # 获取对象
    # queryset = [obj,obj,obj,]
    queryset = models.Order.objects.all()
    
    # values 获取字典
    # queryset = [ {'id':1,'title':"xx"},{'id':2,'title':"xx"}, ]
    queryset = models.Order.objects.all().values("id","title")
    
    # values_list 获取列表
    # queryset = [ (1,"xx"),(2,"xxx"), ]
    queryset = models.Order.objects.all().values_list("id","title")
    

    我们要根据使用场景选择合适的方法。


    总结

    大家喜欢的话,给个,点个关注!给大家分享更多有趣好玩的Python 网页Web开发知识!

    版权声明:

    发现你走远了@mzh原创作品,转载必须标注原文链接

    Copyright 2023 mzh

    Crated:2023-3-1

    欢迎关注 『Django 网页Web开发』 系列,持续更新中
    欢迎关注 『Django 网页Web开发』 系列,持续更新中
    『01. 安装配置Django』
    『02. 创建并运行一个Django项目』
    『03. 初识Django』
    『04. 请求和响应,网页跳转重定向,实战简易表单模拟登陆』
    『05. 数据库操作,实战用户管理』
    『06. 报错:You have 26 unapplied migration(s). Your project may not work properly until you apply the migra』
    『07. 模板语法』
    『08. 实战项目:部门和员工管理系统(01)』
    『09. 实战项目:员工编辑删除功能与靓号管理(02)』
    『10. 实战项目:靓号搜索功能(03)』
    『11. 实战项目:分页与页码跳转功能(04)』
    『12. 实战项目:分页组件的封装 面向接口编程(05)』
    『13. 实战项目:添加用户时的时间选择组件(06)』
    『14. 实战项目:一些面向对象的代码结构优化(07)』
    『15. 实战项目:管理员增删改查,md5密码和密码重置(08)』
    『16. 实战项目:BootStrap类的进一步优化(09)』
    『17. 实战项目:login业务涉及cookie、session、中间件(10)』
    『18. 实战项目:登录时的验证码(11)』
    『19. 实战项目:初识Ajax请求(12)』
    『20. 实战项目:Ajax实战之订单管理与弹出对话框(13)』
    『21. 实战项目:echart数据图表(14)』
    『22. 实战项目:简单的文件上传(15)』
    『23. 实战项目:Excel和form和moudleForm的文件上传(16)』
    【更多内容敬请期待】


    你可能感兴趣的:(python,#,Django网页Web开发,django,前端,ajax)