基于django的点餐网站 (python和django做点菜系统)

博客目录:

......

十二、基于Django+mysql点餐系统设计-第十二篇(移动端:会员下单处理)

十三、基于Django+mysql的点餐系统设计-第十三篇(H5点餐:订单的展示)

十四、Django+mysql(大堂点餐:需求分析和代码逻辑实现梳理、首页展示)

十五、基于Django+mysql的点餐系统设计-第十五篇(大堂点餐:登录)

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

本篇文章介绍登录功能,打起精神来,这次讲的全是干货,涉及的知识点做了一下梳理:

基于django的点餐系统,基于django的点餐网站

先说url路由添加校验功能,如果路由前缀有web/的都必须校验是否登录,url路由是否能提供一种便捷的方式:登陆中间件只针对web/做校验,url路由将前缀带有web/的短链接放到一起,以便进行管理。这种方式python提供了,在web/urls.py中编写代码:

# 为url路由添加请求前缀web/,凡是带此前缀的url地址必须登录后才能访问

path("web/", include([

path('', index.webIndex, name="web_index"), #前台大堂点餐首页

]))

  将前缀带有web/的路由放到include函数中,现在将前台大堂点餐首页的路由放到include函数中,启动工程,访问http://127.0.0.1:8000/web,页面正常。url路由暂时讲到这,现在讲讲登录页面。登录页面也离不开url控制器和MTV逻辑,简单的代码逻辑就不讲了,这里讲一下一些重要的功能点。

  登录页面添加了选择店铺的页面,怎么将店铺选择传到前端展示呢?在web/views/index.py的login函数中将店铺信息从数据库中获取出来,然后选到前端

def login(request):

'''加载登陆表单页'''

shoplist = Shop.objects.filter(status=1)

context = {'shoplist': shoplist}

return render(request, "web/login.html", context)

  web/login.html怎么展示后端传过来的信息呢?这个更简单,拿到后端传过来的数据,将数据遍历后供用户选择就可以了。

<div class="form-group">

<select name="shop_id" class="form-control">

<option value="0"> - - 请选择商铺名称 - - </option>

{% for shop in shoplist %}

<option value="{{ shop.id }}">{{ shop.name }}</option>

{% endfor %}

</select>

</div>

  此外,登录还包括验证码,这个验证码也是很重要的功能之一,上面画思维导图,忘了把这块功能补上去了。忘了补上去不等于就不说这块功能了,哈哈,现在对验证码这块逻辑进行阐述。

  先看templates/web/login.html中验证码的前端代码

<div class="form-group">
 <input type="text" name="code" style="display:inline;width:120px;float:left;" class="form-control" placeholder="验证码">
 <img src="" onclick="" style="float:right;margin: 5px 20px;"/>
</div>

  页面展示如下图

基于django的点餐系统,基于django的点餐网站

  从前端的代码可以看出,需要有后端的逻辑支撑才能在页面展示中对验证码进行变换和验证,万变不离其宗,前后端的交互还是根据url路由器和MTV进行。验证码的 路由编写完后,在view层进行验证码逻辑的输def verify(request):

''' 生成验证码 '''<br>  #引入随机函数模块<br>  import random<br>  from PIL import Image,ImageDraw,ImageFont<br>  # 定义变量,用于画面的背景色、宽、高<br>  bgcolor = (242, 164, 247)<br>  width = 100<br>  height = 25<br>  # 绘制画面对象<br>  im = Image.new('RGB',(width,height), bgcolor)<br>  # 创建画笔对象<br>  draw = ImageDraw.Draw(im)<br>  # 调用画笔的point()函数绘制噪点<br>  for i in range(0, 100):<br>    xy = (random.randrange(0, width), random.randrange(0, height))<br>    fill = (random.randrange(0, 255), 255, random.randrange(0, 255))<br>    draw.point(xy, fill=fill)<br>  # 定义验证码的被选值<br>  str1 = '0123456789'<br>  # 随机选取4个值作为验证码<br>  rand_str = ''<br>  for i in range(0,4):<br>    rand_str += str1[random.randrange(0,len(str1))] <br>  # 构造字体颜色<br>  fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))<br>  # 绘制4个字<br>  draw.text((5, -3), rand_str[0], font=font, fill=fontcolor)<br>  draw.text((25, -3), rand_str[1], font=font, fill=fontcolor)<br>  draw.text((50, -3), rand_str[2], font=font, fill=fontcolor)<br>  draw.text((75, -3), rand_str[3], font=font, fill=fontcolor)<br><br>  #释放画笔<br>  del draw<br>  # 存入session,用于做进一步验证<br>  request.session['verifycode'] = rand_str<br><br>  # 内存文件操作 -->此方法为python3的<br>  import io<br>  buf = io.BytesIO()<br>  # 将图片保存在内存中,文件类型为png<br>  im.save(buf, 'png')<br>  # 将内存中的图片数据返回给客户端,MIME类型为图片png<br>  return HttpRespo nse(buf.getvalue(), 'image/png')<br><br><br>

  此刻,在templates/web/login.html中给验证码添加跳转的路径

<div class="form-group">

<input type="text" name="code" style="display:inline;width:120px;float:left;" class="form-control" placeholder="验证码">

<img src="{% url 'web_verify' %}" onclick="this.src='{% url 'web_verify' %}?sn='+Math.random()" style="float:right;margin: 5px 20px;"/>

</div>

  启动工程,访问登录页面。出现了验码校验的数字,点击数字可以变换更新

基于django的点餐系统,基于django的点餐网站

  按照登录页面正常流来说的话,店铺选择、验证码选择填写的逻辑说完了。现在说一下正确输入店铺选择、验证码、账号密码后的执行逻辑。登录后要在餐品首页展示店铺下的餐品信息。那么"执行登录"的函数需要将店铺下的餐品信息取出来,然后渲染到餐品首页

  在web/views/index.py中定义dologin函数。在此函数中要完成两个重要的功能:1、匹配账号;2、账号匹配成功后,将店铺下的菜品分类、菜品遍历出来存到缓存;3、跳转到餐品首页。

  首先说下账号匹配的需求,用户在页面输入的账号密码和在数据库中的账号密码做匹配,如果匹配到进行下面的代码执行,如果匹配不到,登录页面会有账号密码不正确的校验提示。本篇只讲正常流程,登录页面校验的问题放到下一章节去讲。这里要注意一下:前面咱们讲过,在添加账号密码的时候,用户输入的密码后,在数据库会与password_salt相加,然后生成password_hash。现在要读取密码,也要遵循这一逻辑。先把用户输入的密码与password_salt结合,然后与数据库里的password_hash做匹配。

  其次再说说怎么获取菜品分类、菜品,先通过前端穿过的店铺信息,在数据库匹配菜品分类信息。菜品分类信息匹配到后,将菜品分类的id、name拿出来放到缓存中。接着再通过菜品分类id获取菜品的信息,将对应的菜品信息遍历出来后,菜品信息放到缓存中。

  最后说一下跳转到餐品首页,当程序将账号密码匹配、菜品分类菜品信息的代码执行完后,会跳转到餐品首页。餐品首页前端代码要添加解析菜品分类和菜品的代码。

  dologin函数的代码如下所示:

def dologin(request):
    ''' 执行登录操作 '''
# 根据登录账号获取登录者信息
        user = User.objects.get(username=request.POST['username'])
        # 判断当前用户是否正常或管理员
        if user.status == 6 or user.status == 1:
            # 判断登录密码是否相同
            import hashlib
            md5 = hashlib.md5()
            s = request.POST['pass'] + str(user.password_salt) # 从表单重获取密码并添加干扰值
            md5.update(s.encode('utf-8')) # 将要产生md5的字串放进去
            if user.password_hash == md5.hexdigest():  # 获取md5值
                print("登录成功!")
                # 将当前登录成功的用户信息以webuser为key写入到session中
                request.session['webuser'] = user.toDict()

                # 获取当前店铺信息
                shopob = Shop.objects.get(id=request.POST['shop_id'])
                request.session['shopinfo'] = shopob.toDict()
                # 获取当前店铺中所有菜品类别和菜品信息
                clist = Category.objects.filter(shop_id = shopob.id, status=1)
                categorylist = dict() # 菜品类别(内含有菜品信息)
                productlist = dict() # 菜品信息
                for vo in clist:
                    c = {'id': vo.id, 'name': vo.name, 'pids':[]}
                    plist = Product.objects.filter(shop_id=shopob.id,category_id=vo.id,status=1)
                    for p in plist:
                        c['pids'].append(p.toDict())
                        productlist[p.id] = p.toDict()
                    categorylist[vo.id] = c
                    request.session['categorylist'] = categorylist #菜品类别列表
                    request.session['productlist'] = productlist #菜品列表
                    #重定向到前台大堂点餐首页
                    return redirect(reverse("web_index"))
           

  现在看看餐品首页的代码逻辑怎么实现呢?编写遍历菜品分类和菜品信息的代码逻辑:

......

<div class="col-md-8">

<!--标签页内容-->

{% for key,category in categorylist %}

<h5 style="padding-bottom: 9px;border-bottom: 1px solid #eee;color: #BB3D00"><span class="glyphicon glyphicon-list" aria-hidden="true">{{ category.name }}</h5>

<div class="row shoplist">

{% for product in category.pids %}

<div class="col-sm-6 col-md-3">

<div class="thumbnail">

<img src="{% static 'uploads/product' %}/{{ product.cover_pic }}" alt="...">

<div class="caption">

<h6>{{ product.name }}</h6>

<a class="bn">¥<span class="price">{{ product.price }}</span>元</a>

<a href="" class="btn btn-warning btn-xs pull-right" role="button"><span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span> 购买</a></div>

</div>

</div>

{% endfor %}

</div>

{% endfor %}

</div>

......

  好了,前后端的代码都写完了,启动工程访问大堂点餐,登录后跳转到餐品首页,咦,菜品信息怎么没有展示出来,检查了前后端的代码没有问题呢。debug代码原来是餐品首页读取不到餐品分类和菜品的信息。怎么解决这个问题呢?在web/views/index.py中的webIndex.函数中获取菜品分类的缓存信息,然后渲染到前端页面。

<em id="__mceDel"><em id="__mceDel">context = {'categorylist': request.session.get("categorylist", {}).items()}</em>

</em>

  再次访问餐品首页,餐品展示出来了。

基于django的点餐系统,基于django的点餐网站

  本片到此结束,下一篇开始将登录页面的校验规则。

#头条创作挑战赛#