oores是干净和现代的餐厅HTML5站点模板,可以用作咖啡馆和餐馆,或任何食物相关业务的网站。可以展示餐厅的美食或者在线下单订餐等。
有需要的同学可以前往网站下载。
Bootstrap介绍。
Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。
在现代 Web 开发中,有几个几乎所有的 Web 项目中都需要的组件。
Bootstrap 为您提供了所有这些基本的模块 - Grid、Typography、Tables、Forms、Buttons 和 Responsiveness。
此外,还有大量其他有用的前端组件,比如 Dropdowns、Navigation、Modals、Typehead、Pagination、Carousal、Breadcrumb、Tab、Thumbnails、Headers 等等。
有了这些,你就可以搭建一个 Web 项目,并让它运行地更快速更轻松。
此外,由于整个框架是基于模块的,您可以通过您自己的 CSS 位,甚至是项目开始后的一个大整改,来进行自定义。
bootstrap有什么用?
使用bootstrap框架可以响应式网站,bootstrap能使用适用pc和手机等不同分辨率的设备,我们不需要根据设备的不同而去担心显示效果。目前所有的浏览器都支持Bootstrap,所以我们在做网站的时候,也不要考虑浏览器的兼容问题。
Bootstrap的优点是什么?
提供了一套完整的流式栅格系统,可以自动适应设备屏幕的大小,而且能快速地完成网站的搭建,bootstrap预先有很多的css类,例如,text-align,我们在使用的时候,直接命名即可,并且提供了很多插件,来供开发者使用,当然你也可以定制组件,来完成网站的制作。
要
现如今,人们的生活节奏加快于是就对用餐的时间有了一定的要求。随着计算机网络技术的发展,结构目前手机的普及。在线订餐系统也就运营而出了,不仅可以解决用户的用餐问题同时还解决了餐厅的销量。通过对点餐系统的设计,改变了传统了点餐方式通过电子信息和信息化技术来实现不接触点餐,避免了人手不足造成的点餐取餐时间过长的问题。随着互联网技术的发展,点餐系统的开发技术逐渐成熟,开发成本也快速的下降。
本系统的开发和运行将会给人们的用餐带来巨大的便捷,使得用餐摆脱了时间和空间的限制。本系统内部后台采用Java开发,系统的总体划分为前端和后端。前端模块主要是用来展示现相关的订餐页面和餐点的数据渲染;后端则主要体用一些业务和逻辑上的处理服务。课题将运用电子商务系统规划设计与分析理论,项目管理理论,Push技术理论等。对中国点餐系统的运营模式发展的基础上,设计一套切实可行的点餐系统。
关键词:在线订餐;点餐系统;UML;软件开发;MySQL数据库
Abstract
Nowadays, people's pace of life accelerates, so there are certain requirements for dining time. With the development of computer network technology, the structure of the current popularity of mobile phones. The online ordering system is also operational, which can not only solve the problem of users, but also solve the sales of restaurants. Through the design of the ordering system, the traditional way of ordering is changed through electronic information and information technology to achieve no contact ordering, avoiding the problem of too long ordering time caused by the lack of manpower. With the development of Internet technology, the development technology of the ordering system is gradually mature, and the development cost is also falling rapidly reduced.
The development and operation of this system will bring great convenience to people's dining, so that the dining can get rid of the limitation of time and space. The internal background of the system is developed by Java, and the overall system is divided into front end and back end. The front-end module is mainly used to show the data rendering of the relevant ordering pages and meals; the back-end module mainly uses some business and logical processing services. The project will use the theory of electronic commerce system planning, design and analysis, project management theory, Push technology theory, etc. On the basis of the development of the operation mode of the Chinese ordering system, a set of practical ordering system is designed.
Keywords: Online ordering; ordering system; UML; software development; MySQL database
目 录
第1章 引言 1
1.1 研究背景 1
1.2 选题意义 1
1.3 研究现状 1
1.4 研究内容 3
1.5 论文结构 3
第2章 相关理论概述 4
2.1 HTML简介 4
2.2 层叠样式表技术 4
2.3 AJAX技术 4
2.4 MySQL数据库 4
第3章 点餐平台系统分析 6
3.1 需求概述 6
3.2 功能需求分析 6
3.3 非功能需求分析 8
3.4 可行性分析 8
第4章 系统的详细设计 10
4.1 系统架构 10
4.2 系统主要模块功能设计 11
4.3 数据库设计 12
第5章 点餐平台的实现 16
5.1 点餐平台前台实现 16
5.2 点餐平台后台实现 23
第6章 点餐平台测试 27
6.1 系统测试目标 27
6.2 测试方法 27
6.3 测试用例 27
6.4 测试结果 29
第7章 总结 30
参考文献 31
致 谢 31
针对不同用户需求,本系统主要划分了两类用户用例,主要有用户和管理员组成,每一组不同的用例都包含了不同的系统模块和使用权限。
(1)系统遵循开放模式,注册用户可以按照自己的需要查看配件和账单结算;未注册用户也可以任意查看,但在生成订单时要求正式登陆系统。
(2)菜品信息主要包括编码、名称、类型、活动、描述和图片等。
(3)提供查询功能,可实现关键字模糊查询,按照类别和活动查询。
(4)购物车中要清楚显示编码、名称、价格和数量,并显示总价格。
(5)为了方便用户的操作,可以直接在购物车中删除配件,如果用户想继续购买,通过点击该连接可再次购买,更新数量。
(6)用户在关闭浏览器之前,可随时查看自己的购物车,并可随时下订单。
(7)用户可以查看自己的订单,并且可以更改订单状态。
(1)管理员拥有最大权限,可以进入管理页面并配置系统信息。
(2)管理员可以管理会员,对用户信息进行删除。
(3)管理员可以随时更新菜品信息,上传新菜品,以及删除菜品。
(4)管理员查看订单,并更新订单状态。
明:本次文章是看了B站上的视频和分享的代码笔记后,自己敲了一遍代码。然后再敲一遍代码的同时写文章梳理逻辑,看不懂的同学可以去看原文章和视频。文章如有雷同,可联系我删除!视频链接:
https://www.bilibili.com/video/BV1pq4y1W7a1?spm_id_from=333.999.0.0
博客目录:
一、基于Django+mysql的点餐系统设计--第一篇(开篇:确认需求功能、数据库设计、程序设计)
二、基于Django+mysql的点餐系统设计--第二篇(搭建工程、前后端调试)
三、基于Django+mysql的点餐系统设计--第三篇(编写后台员工管理页面)
四、基于Django+mysql的点餐系统设计--第四篇(编写后台菜品分类管理功能)
五、基于Django+mysql的点餐系统设计--第五篇(编写后台店铺管理页面)
六、基于Django+mysql的点餐系统设计-第六篇(编写后台菜品管理页面)
本章源码下载地址:https://github.com/hopeSuceess/testorder/tree/testorder_2022051501
写到第六篇简单的增删改查已经都非常熟悉了,这里不做过多阐述,本篇针对以下重点功能进行说明:父页面添加路径、外键、菜品分类浏览页的查看菜品、图片修改(另一种考虑更全面的方式)、商铺和菜品分类的二级联动。
前端父页面添加路径比较简单,但是非常重要。它是菜品管理页面展示的入口,相关示例图和代码如下
外键对于数据表来说是很常见的,怎么将外键展示到页面是一个技术点。前面讲菜品分类管理的时候涉及到外键了,这次菜品管理涉及到店铺、菜品分类两个外键,但是从技术逻辑来说,菜品管理的外键展示和菜品分类管理的展示差不多,具体代码如下:
for vo in list2:
shopDetail=Shop.objects.get(id=vo.shop_id)
vo.shopname=shopDetail.name
categoryDetail=Category.objects.get(id=vo.category_id)
vo.categoryname=categoryDetail.name
菜品分类浏览页的查看菜品:前面在讲菜品分类管理的时候有一个"查看菜品"的功能没有实现。在写完菜品分类管理的代码后可以实现这一功能了。
现在开始实现查看菜品的功能,首先在myadmin/urls.py中添加菜品分类的路由
path('product/category/<int:sid>', product.categoryProduct, name="myadmin_categoryProduct_index"), #菜品分类-查看菜品浏览页
确定完url控制器,开始在views视图中写具体的逻辑,在myadmin/views/product.py中的实现看下图
def categoryProduct(request,sid,pIndex=1):
'''浏览信息'''
list=Product.objects.filter(status__lt=9, category_id=sid)
# smod=Product.objects
# list=smod.filter(status__lt=9)
mywhere=[]
# 获取、判断并封装keyword建搜索
kw=request.GET.get("keyword", None)
if kw:
# 查询店铺名称中只要含有关键字就可以
list=list.filter(Q(price__contains=kw) | Q(name__contains=kw))
mywhere.append("keyword=" + kw)
list=list.order_by("id") # 对id排序
# 执行分页处理
pIndex=int(pIndex)
page=Paginator(list, 5) # 以5条每页创建分页对象
maxpages=page.num_pages # 最大页数
# 判断页数是否越界
if pIndex > maxpages:
pIndex=maxpages
if pIndex < 1:
pIndex=1
list2=page.page(pIndex) # 当前页数据
plist=page.page_range # 页码数列表
for vo in list2:
shopDetail=Shop.objects.get(id=vo.shop_id)
vo.shopname=shopDetail.name
categoryDetail=Category.objects.get(id=vo.category_id)
vo.categoryname=categoryDetail.name
# 封装信息加载模板输出
context={"productlist": list2, 'plist': plist, 'pIndex': pIndex, 'maxpages': maxpages, 'mywhere': mywhere}
return render(request, "myadmin/product/categoryProduct.html", context)
写完了views视图层开始写templates展示层,在templates/product目录下写一个categoryProduct.html页面,categoryProduct.html页面的内容如下:
{% extends "myadmin/base.html" %}
{% block main_body %}
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
菜品信息管理
<small>订餐系统后台管理</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> 首页</a></li>
<li class="active">菜品信息管理</li>
</ol>
</section>
<!-- Main content -->
<section class="content container-fluid">
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
<h3 class="box-title"><i class="fa fa-calendar"></i> 菜品信息表</h3>
</div>
<!-- /.box-header -->
<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 width="45">状态</th>
<th>添加时间</th>
</tr>
{% for vo in productlist %}
<tr>
<td>{{ vo.id }}</td>
<td>{{ vo.shopname }}</td>
<td>{{ vo.categoryname }}</td>
<td><img src="/static/uploads/product/{{ vo.cover_pic }}" width="30"/></td>
<td>{{ vo.name }}</td>
<td>{{ vo.price }}</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="10%">{{ vo.create_at|date:'Y-m-d' }}</td>
</tr>
{% endfor %}
</table>
</div>
<!-- /.box-body -->
<div class="box-footer clearfix">
<ul class="pagination pagination-sm no-margin pull-right">
<li><a href="{% url 'myadmin_product_index' pIndex|add:-1 %}?{{ mywhere|join:'&' }}">?</a></li>
{% for p in plist %}
<li {% if pIndex==p %}class="active"{% endif %}><a href="{% url 'myadmin_product_index' p %}?{{ mywhere|join:'&' }}">{{ p }}</a></li>
{% endfor %}
<li><a href="{% url 'myadmin_product_index' pIndex|add:1 %}?{{ mywhere|join:'&' }}">?</a></li>
</ul>
</div>
</div>
<!-- /.box -->
</div>
</div>
</section>
<!-- /.content -->
{% endblock %}
templates展示层也搞定了,现在需要在templates/category/index.html的"查看菜品"标签下放一个路径进行调试了,如下:
<a href="{% url 'myadmin_categoryProduct_index' vo.id %}" class="btn btn-warning btn-xs">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span> 查看菜品</a>
在菜品分类浏览页,点击查看菜品,跳到了菜品详情页:
在上一篇店铺管理中涉及到了图片上传和修改的功能,在本篇继续介绍图片修改(另一种考虑更全面的方式)。在菜品修改时,考虑更全面的代码如下:
#后端代码
def update(request,sid):
try:
# 获取原图片
oldpicname=request.POST['oldpicname']
# 图片的上传处理
myfile=request.FILES.get("cover_pic", None)
if not myfile:
cover_pic=oldpicname
else:
cover_pic=str(time.strftime("%Y%m%d.%H%M%S"))+"."+myfile.name.split('.').pop()
destination=open("./static/uploads/product/"+cover_pic, "wb+")
for chunk in myfile.chunks():
destination.write(chunk)
destination.close()
productList=Product.objects.get(id=sid)
productList.shop_id=request.POST['shop_id']
productList.category_id=request.POST['category_id']
productList.name=request.POST['name']
productList.price=request.POST['price']
productList.cover_pic=request.POST['cover_pic']
productList.update_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
productList.save()
context={'info': '修改成功!'}
# 判断并删除老图片
if myfile:
os.remove("./static/uploads/product/"+oldpicname)
except Exception as err:
print(err)
context={'info': '添加失败!'}
# 判断并删除新图片
if myfile:
os.remove("./static/uploads/product/"+cover_pic)
return render(request, "myadmin/info.html", context)
templates/myadmin/product/edit.html图片更改的前端代码如下:
......
<input type="hidden" name="oldpicname" value="{{ product.cover_pic }}" />
......
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">菜品图片:</label>
<div class="col-sm-4">
<input type="file" name="cover_pic" /><br/>
<img src="/static/uploads/product/{{ product.cover_pic }}" width="200"/>
</div>
</div>
......
菜品在新增或修改之前,需要带出来其属于哪个商铺下的哪个菜品分类。本篇在实现菜品新增、修改的功能时,在后端传入商铺信息,前端在解析后端传过来的商品信息时,通过ajax调用相对应的菜品分类信息,商铺和菜品分类的二级联动是本篇非常重要的一个知识点和功能点。
这里以新增菜品为例,阐述商铺和菜品分类的二级联动。myadmin/views/product.py中add函数获取店铺信息并渲染到前端,代码如下:
def add(request):
"""加载信息添加表单"""
# 获取当前所以店铺
slist=Shop.objects.values("id", "name")
context={"shoplist": slist}
return render(request, "myadmin/product/add.html", context)
templates/myadmin/product/add.html中,店铺标签接收后端传过来的店铺信息,如下:
<div class="col-sm-4">
<select name="shop_id" id="shop_id" onchange="doLoadCategory()" class="form-control select2" style="width: 100%;">
{% for svo in shoplist %}
<option value="{{ svo.id }}">{{ svo.name }}</option>
{% endfor %}
</select>
</div>
在上面的代码中,大家可以看到doLoadCategory函数,没错,店铺级联菜品分类靠的就是doLoadCategory函数。在调用店铺标签时会自动调用doLoadCategory函数,从而实现店铺和菜品分类的同步展示。下边看下doLoadCategory函数的代码实现:
//自定义函数,实现通过店铺id,Ajax加载对应的菜品分类信息
function doLoadCategory(){
//获取选中的id号
var id=$("#shop_id").val();
$("#category_id").empty();
$.ajax({
url: "/myadmin/category/load/"+id,
type: 'get',
data: {},
dataType:'json',
success:function(res){
if(res.data.length<1)
return;
var data=res.data;
var select=$("#category_id")
for(var i=0;i<data.length;i++){
$('<option value="'+data[i].id+'">'+data[i].name+'</option>').appendTo(select)
//select.append('<option value="'+data[i].id+'">'+data[i].name+'</option>');
}
}
});
}
这里说下doLoadCategory函数中的 url: "/myadmin/category/load/"+id, 它对应myadmin/urls.py中的
path('category/load/<int:sid>', category.loadCategory, name="myadmin_category_load"), 该路由通过调用loadCategory函数实现对应店铺下菜品分类的展示。
loadCategory函数实现逻辑如下:
def loadCategory(request,sid):
clist=Category.objects.filter(status__lt=9,shop_id=sid).values("id","name")
# 返回QuerySet对象,使用list强转成对应的菜品分类列表信息
print(clist)
print(list(clist))
return JsonResponse({'data': list(clist)})
最后看下商铺和菜品分类二级联动的效果图:
好了,本篇的重点功能讲完了,下一篇讲一下后台账号管理页面
*请认真填写需求信息,我们会在24小时内与您取得联系。