欧易

欧易(OKX)

国内用户最喜爱的合约交易所

火币

火币(HTX )

全球知名的比特币交易所

币安

币安(Binance)

全球用户最多的交易所

基于Django mysql的点餐系统设计--第四篇(编写后台菜品分类管理)

2023-06-01 14:57:43 1373

摘要:声明:本次文章是看了B站上的视频和分享的代码笔记后,自己敲了一遍代码。然后再敲一遍代码的同时写文章梳理逻辑,看不懂的同学可以去看原文章和视频。文章如有雷同,可联系我删除!视频链接:https://www.bilibili.com/video...

声明:本次文章是看了B站上的视频和分享的代码笔记后,自己敲了一遍代码。然后再敲一遍代码的同时写文章梳理逻辑,看不懂的同学可以去看原文章和视频。文章如有雷同,可联系我删除!视频链接:https://www.bilibili.com/video/BV1pq4y1W7a1?spm_id_from=333.999.0.0

博客目录:

一、基于Django+mysql的点餐系统设计--第一篇(开篇:确认需求功能、数据库设计、程序设计)

二、基于Django+mysql的点餐系统设计--第二篇(搭建工程、前后端调试)

三、基于Django+mysql的点餐系统设计--第三篇(编写后台员工管理页面)

四、基于Django+mysql的点餐系统设计--第四篇(编写后台菜品分类管理功能)

本章源码下载地址:https://github.com/hopeSuceess/testorder/tree/testorder_20220221_01

前段时间因为工作忙断更了,做事情有始有终嘛,抽出来事情还是要把这个系列做完。

   刚刚捋了一下逻辑,遇到两个问题:一个是新增菜品类别时,菜品类别为空判断不生效;另一个是github好久不用了,它在2022.3.15更改了加密方式导致代码提交不上去。解决完这两个问题,有一些感慨:出现问题不可怕,只要静下心去解决,问题都会完美解决。

   好了,回到正题。应用层的高级语言编写程序,实现的逻辑基本上都是增删改查,上一篇写完了后台员工管理的功能,本篇的后台店铺管理、菜品分类管理也基本上大同小异。基本的逻辑是在models层定义数据库表和字段,去URL控制器编写对应的路由,然后再到views层编写具体的增删改查方法,最后views层将逻辑渲染到页面(templates层)。当然了templates层也有一些逻辑,诸如页面继承、ajax、循环控制、逻辑判断等等。

   咱们先从菜品分类开始说起,在myadmin/models.py下定义菜品分类的数据表,如下图:

# 菜品分类信息模型
class Category(models.Model):
    shop_id = models.IntegerField()        # 店铺id
    name = models.CharField(max_length=50) # 分类名称
    status = models.IntegerField(default=1) # 状态:1正常/2禁用/9删除
    create_at = models.DateTimeField(default=datetime.now) # 创建时间
    update_at = models.DateTimeField(default=datetime.now) # 修改时间

    class Meta:
        db_table = "category" # 更改表名

定义完数据表,可以在myadmin/urls.py定义菜单分类的路由,包括列表浏览页、添加表单、执行添加、修改表单、执行修改、删除

    # 菜品分类信息管理
    path("category/<int:pIndex>", category.index, name="myadmin_category_index"),  # 列表浏览页
    path("category/add", category.add, name="myadmin_category_add"), # 添加表单
    path("category/insert",category.insert, name="myadmin_category_insert"), # 执行添加
    path("category/edit/<int:sid>", category.edit, name="myadmin_category_edit"), # 修改表单
    path("category/update/<int:sid>", category.update, name="myadmin_category_update"), # 执行修改
    path("category/delete/<int:sid>",category.delete, name="myadmin_category_delete"), # 删除

根据MTV思想,url控制器和M(models)都定义好了,咱们开始看V(views)。业务逻辑像数据的增、删、改、查等基本上都在views层处理,下面运用思维导图对菜品分类的增删改查的逻辑展示下:

views层的代码如下:

# 菜品分类信息
from datetime import datetime
from django.core.paginator import Paginator
from django.http import JsonResponse
from django.shortcuts import render

from myadmin.models import Category, Shop


def index(request,pIndex=1):
    """浏览信息"""
    smod = Category.objects
    mywhere = []
    list = smod.filter(status__lt=9)

    # 获取、判断并封装keyword键搜索条件
    kw = request.GET.get("keyword", None)
    if kw:
        list = list.filter(name__contains=kw)
        mywhere.append("keyword=" + kw)
    # 获取、判断并封装状态status搜索条件
    status = request.GET.get("status", "")
    if status != "":
        list = list.filter(status=status)
        mywhere.append("keyword=" + status)

    list = list.order_by("id") # 对id排序
    # 执行分页处理
    pIndex = int(pIndex)
    page = Paginator(list, 10) #以10条每页创建分页对象
    maxpages = page.num_pages # 最大页数
    # 判断页数是否越界
    if pIndex > maxpages:
        pIndex = maxpages
    if pIndex < 1:
        pIndex = 1
    list2 = page.page(pIndex) # 当前页数据
    plist = page.page_range # 页码数列表

    # 遍历信息,并获得对应的商铺名称,以shopname名封装
    for vo in list2:
        sob = Shop.objects.get(id=vo.shop_id)
        vo.shopname = sob.name
    # 封装信息加载模板输出
    context = {"categorylist": list2, "plist": plist, "pIndex": pIndex, "maxpages": maxpages, "mywhere": mywhere}
    return render(request, "myadmin/category/index.html", context=context)


# def loadCategoy(request,sid):
#     clist = product.objects.filter(status__lt=9,shop_id=sid).values("id","name")
#     # 返回QuerySet对象,使用list强转成对应的菜品分类列表信息
#     return JsonResponse({"data": list(clist)})


def add(request):
    """加载添加页面"""
    slist = Shop.objects.values("id", "name")
    context = {"shoplist":slist}
    return render(request, "myadmin/category/add.html",context)


def insert(request):
    """ 执行表单添加 """
    try:
        cod = Category()
        cod.shop_id = request.POST["shop_id"]
        categoryName = request.POST.get("name", None)
        if categoryName:
            cod.name = categoryName
        else:
            context = {"info": "菜品分类不能为空"}
            return render(request, "myadmin/info.html", context)
        cod.status = 1
        cod.create_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        cod.update_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        cod.save()
        context = {"info": "新增成功!"}
    except Exception as e:
        print(e)
        context = {"info": "新增失败!"}
    return render(request, "myadmin/info.html", context)


def delete(request,sid):
    dataDel = Category.objects.get(id=sid)
    del dataDel
    context = {"info": "删除成功!"}
    return render(request,"myadmin/info.html",context)


def edit(request,sid):
    category = Category.objects.get(id=sid)
    slist = Shop.objects.values("id", "name")
    context = {"shoplist": slist, "category": category}
    return render(request, "myadmin/category/edit.html",context)


def update(request,sid):
    category = Category.objects.get(id = sid)
    category.shop_id = request.POST["shop_id"]
    category.name = request.POST["name"]
    category.status = request.POST["status"]
    category.update_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    category.save()
    context = {"info": "修改成功!"}
    return render(request, "myadmin/info.html", context)

根据MTV思想脉络走,写完了views层开始写T(templates)层了,毕竟views层逻辑结果的输出要通过templates层展现出来。templates层对应的是html页面,先来说说myadmin/views/index中的index函数渲染的myadmin/category/index.html。index就是列表浏览页,它的涉及的功能点,如下:

模糊查询/精准查询,代码如下:

<div class="box-tools">
{#点击查询页面跳转的地址是myadmin_category_index,对应的还是myadmin/views/index中的index函数#}
  <form action="{% url "myadmin_category_index" 1 %}" method="get">
  <div class="input-group input-group-sm" style="width: 150px;">
{#name="keyword"将输入的值传送到后端index函数进行逻辑判断#}
    <input type="text" name="keyword" class="form-control pull-right" placeholder="Search">
    <div class="input-group-btn">
      <button type="submit" class="btn btn-default"><i class="fa fa-search"></i></button>
    </div>
  </div>
  </form>
</div>

 循环控制语句遍历后端传过来的数据,代码如下:

            <div class="box-body table-responsive no-padding">
              <table class="table table-hover">
                <tr>
                  <th>ID</th>
                  <th>店铺名称</th>
                  <th>类别名称</th>
                  <th>当前状态</th>
                  <th>添加时间</th>
                  <th>修改时间</th>
                  <th>操作</th>
                </tr>
                {% for vo in categorylist %}
                <tr>
                  <td>{{ vo.id }}</td>
                  <td>{{ vo.shopname }}</td>
                  <td>{{ vo.name }}</td>
                  <td>
                    {% if vo.status == 1 %}
                      <span style="color:green">正常</span>
                    {% elif vo.status == 2 %}
                        <span style="color: red">禁用</span>
                    {% elif vo.status == 9 %}
                      <span style="color:red">已删除</span>
                    {% else %}
                      <span style="color:red">未知状态</span>
                    {% endif %}
                  </td>
                  <td width="12%">{{ vo.create_at|date:"Y-m-d" }}</td>
                  <td width="12%">{{ vo.update_at|date:"Y-m-d" }}</td>
                  <td width="25%">
                    <a href="{% url "myadmin_category_edit" vo.id %}" class="btn btn-success btn-xs">
                      <span class="glyphicon glyphicon-edit" aria-hidden="true"></span> 编辑</a>
                    <button type="button" onclick="doDel("{% url "myadmin_category_delete" vo.id %}")" class="btn btn-danger btn-xs">
                      <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> 删除</button>
{#                    <a href="{% url "myadmin_category_load" vo.id %}" class="btn btn-warning btn-xs">#}
{#                      <span class="glyphicon glyphi con-search" aria-hidden="true"></span> 查看菜品</a>#}
                  </td>
                </tr>
                {% endfor %}
              </table>
            </div>

分页的逻辑判断,代码如下:

              <ul class="pagination pagination-sm no-margin pull-right">
                    <li><a href="{% url "myadmin_category_index" pIndex|add:-1 %}?{{ mywhere|join:"&" }}">«</a></li>
                    {% for p in plist %}
                    <li {% if p == pIndex %}class="active"{% endif %}><a href="{% url "myadmin_category_index" p %}?{{ mywhere|join:"&" }}">{{p}}</a></li>
                    {% endfor %}
                    <li><a href="{% url "myadmin_category_index" pIndex|add:1 %}?{{ mywhere|join:"&" }}">»</a></li>
                </ul>

列表浏览页长啥样呢,如下图:

  写到这里,菜品分类的查询功能一个闭环流程算写完了。如果有同学跟着我的博客敲代码,建议参照源码先把一个查询功能写出来,然后再一点点的写增、删、改。

接下来开始写templates层增、改。是菜品分类的新增页面,在列表浏览页点击"添加菜品分类"会通过myadmin/views/index.py的渲染后跳转到templates/myadmin/category/add.html页面。add.html最重要的一个功能点是将店铺名称展示出来,代码如下:

  <label for="inputEmail3" class="col-sm-2 control-label">店铺名称:</label>

                  <div class="col-sm-4">
                    <select name="shop_id" class="form-control select2" style="width: 100%;">
                        {% for svo in shoplist %}
                            <option value="{{ svo.id }}">{{ svo.name }}</option>
                        {% endfor %}
                    </select>
                  </div>

add.html页面长得模样如下图:

在add.html页面填写完类别名称,点击提交.就会调用myadmin/views/category.py中的update函数了。不管成功与否,后端的update函数通过渲染templates/myadmin/info.html,将成功与否的信息展现给用户。

info.html代码如下:

{% extends "myadmin/base.html" %}

{% block main_body %}
    <section class="content-header">
        <h4>
           信息提示:
        </h4>
    </section>

    <div class="pad margin no-print">
        <div class="callout callout-info" style="margin-bottom: 0!important;padding-left: 50px">
            <h3><i class="fa fa-exclamation-triangle"></i> {{ info }}</h3>
        </div>
    </div>

{% endblock %}

  templates层增、改说完了,有必要回味总结一下,写到这里感觉处处都是知识点。

  现在开始说templates的修改,流程逻辑:用户在列表浏览页(templates/myadmin/category/index.html)点击"编辑" --> 后端views层(myadmin/views/category的edit函数)处理逻辑,将结果渲染到编辑页(templates/myadmin/category/edit.html) 。edit页面要针对后端传过来的数据做一下逻辑处理。像店铺信息后端直接将数据打包就以字典的形式扔给了前端,前端要把店铺信息和分类信息一一对应上。具体看下面的代码实现:

<div class="col-sm-4">
                    <select name="shop_id" class="form-control select2" style="width: 100%;">
                      {% for svo in shoplist %}
                        <option value="{{ svo.id }}" {% if category.shop_id == svo.id %}selected{% endif %} >{{ svo.name }}</option>
                      {% endfor %}
                    </select>
                  </div>

 另外,状态的修改也需要关注一下,菜品分类数据表中1代表正常,2代表禁用,怎么将状态友好的展示给用户呢,看下面的代码实现:

<div class="controls">
                         
                      <input type="radio" name="status" class="input-xlarge" value="1" 
                      {% if category.status == 1 %}checked{% endif %} /> 正常
                           
                      <input type="radio" name="status" class="input-xlarge" value="2" 
                      {% if category.status == 2 %}checked{% endif %} /> 禁用
                    </div>

 edit.html页面展示如下图:

至此,后台管理的菜品分类模块讲完了,大家可以捋一下流程,多敲一下代码,熟能生巧。下一章说下店铺管理的要点,下一章见啦~

版权声明:本站所有文章皆是来自互联网,如内容侵权可以联系我们( 微信:bisheco )删除!
友情链接
币圈社群欧易官网