百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

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

bigegpt 2024-09-20 13:53 3 浏览

声明:本次文章是看了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页面展示如下图:

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

相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...