项目实战-后台员工信息管理(增删改查登录与退出)

     阅读:22

代码在以下~https://gitee.com/hedyyi/myobject.git

以下为笔记~

项目搭建:
1.创建项目:django-admin startproject myobject
2.创建应用:python manage.py startapp myadmin/web/mobile
3.创建模板目录:templates(模板中对应各应用目录myadmin/web/mobile)
4.创建静态资源目录:static(目录中对应各应用目录myadmin/web/mobile,并放置图片文件uploads)
5.在每一个应用目录下创建视图包views并删除原有的views.py (init.py和index.py)
5.将项目myobject中的路由文件url.py复制一份到各应用目录下

6.项目框架配置;项目myobject目录下setting.py文件
1. 配置允许访问的主机名信息 ALLOWED_HOSTS = ['*']
2. 将myadmin,web,mobile的应用添加到项目框架结构中 INSTALLED_APPS
3. 配置模板目录 os.path.join(BASE_DIR,'templates') TEMPLATES
4. 配置项目的数据库连接信息;DATABASES
5. 设置时区和语言 LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'
6. 配置网站的静态资源目录 STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]

7.项目myobject目录下路由urls.py配置
引入包

from django.urls import include
urlpatterns = [
#path('admin/', admin.site.urls),
path('', include("web.urls")),                # 默认前台大堂点餐端
path('myadmin/', include("myadmin.urls")),     # 后台管理端
path('mobile/', include("mobile.urls")),    # 移动会员端
]

8.在各应用目录下路由urls.py配置

from django.urls import path
from myadmin.views import index
urlpatterns = [
    # 后台首页
    path('', index.index, name="myadmin_index"),
]

9.在各应用目录下视图 views/index.py配置

   from django.shortcuts import render
    from django.http import HttpResponse
    #后台首页
    def index(request):
        return HttpResponse('欢迎进入点餐系统网站后台管理!')

10.运行测试;在项目根目录下启动服务;python manage.py runserver

11.摆放后台首页面(涉及前端内容)从github上下载一个后台简洁模板:https://github.com/ColorlibHQ/AdminLTE

12.将模板里面的bower_components、dist、local、package.json复制到项目的后台静态资源目录static/myadmin/中

13.在templates/myadmin创建index目录,里面创建index.html文件,将github下载下来的html页面内容复制进来,将里面的路径进行填充{% static 'myadmin/... '%}

14.在templates/myadmin创建base.html文件,以便继承使用,将index.html里面的内容全剪切过来,将不需要继承的地方剪切并进行占位 {% block main_body %} {% endblock %}

15.回到index.html文件中进行继承;{% extends 'myadmin/base.html' %};表示继承myadmin下面的base.html文件

{% block main_body %}
上一步剪切的东西复制过来
{% endblock %}

项目实战-后台员工信息管理-
16.在数据库中创建user表(员工账号id,员工账号,昵称,密码,密码干扰值,状态,创建时间,修改时间)
17.定义Model类(myadmin/models.py);定时列表中的字段信息
18.新增视图文件(myadmin/views/user.py),主要定义增删改查的方法;
18.配置urls路由信息;(myadmin/urls.py),将定义的增删改查的方法路由放进去
19.编辑后台模板,创建templates/myadmin/user/index.html,继承base.html内容 并将AdminLTE中部分内容复制进去修改复制到index.html即可(主要改下列表显示的字段信息以及进行循环并各种判断)
20.编辑base.html内容,将首页和员工管理的地址进行反解析,首页{% url ‘myadmin_index’ %};员工管理{% url ‘myadmin_user_index’ %}

21.列表分页操作;在myadmin/views/user.py浏览方法里添加分页操作;
22.templates/myadmin/user/index.html文件中循环列表数据,以及加上选中当前页面以及上一页下一页的判断

23.列表搜索;复制搜索条件到index.html (

)下面

              <div class="input-group-btn">
                <button type="submit" class="btn btn-default"><i class="fa fa-search"></i></button>
              </div>
            </div>
            </form>

24.在myadmin/views/user.py中继续封装完善方法;
“”“获取,判断并封装keyword键搜索”“”
mywhere = []
kw = request.GET.get(“keyword”,None)
if kw:
#ulist = ulist.filter(username__contains=kw) #单个搜索
ulist = ulist.filter(Q(username__contains=kw) | Q(nickname__contains=kw)) #Q是表示为且的关系
mywhere.append(“keyword=”+kw)

25.在index.html完善根据搜索条件翻页的时候也能被选中

  <li><a href="{% url 'myadmin_user_index' pIndex|add:-1 %}?{{ mywhere|join:'&' }}">&laquo;</a></li>
                  {% for p in plist %}
                {#根据判断条件数据当前页列表#}
                <li {% if p == pIndex %} class="active"{% endif %}><a href="{% url 'myadmin_user_index' p %}?{{ mywhere|join:'&' }}">{{ p }}</a></li>
                  {% endfor %}
                {#下一页#}
                <li><a href="{% url 'myadmin_user_index' pIndex|add:1 %}?{{ mywhere|join:'&' }}">&raquo;</a></li>

26.添加操作;myadmin/views/user.py
add;仅加载页面return render(request, "myadmin/user/add.html")
insert执行添加;return render(request, "myadmin/info.html", context);进行添加操作需要的内容封装

27.创建myadmin/user/add.html;在AdminLTE中找到add.html相关的,复制部分即可;记得继承

{% extends “myadmin/base.html” %}
{% block main_body %}
这里放置添加的内容
{% endblock %}

28.创建myadmin/info.html;主要是为了添加成功后的提示。

{% extends "myadmin/base.html" %}
{% block main_body %}
    <!-- Content Header (Page header) -->
    <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>  &nbsp; {{ info }}</h3>
      </div>
    </div>
{% endblock %}

29.在myadmin/user/indexl.html;更改add.html这部分内容;

 <a role="button" href="{% url 'myadmin_user_add' %}" class="btn btn-primary">

30.即可在页面添加操作成功

31.删除操作;myadmin/views/user.py;继续封装完善

def delete(request,uid=0):
    '''执行添加'''
    try:
        ob = User.objects.get(id=uid)
        ob.status = 9
        ob.update_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        ob.save()
        context = {"info": "删除成功!"}
    except Exception as err:
        print(err)
        context = {"info": "删除失败"}
    return render(request, "myadmin/info.html", context)

32.在myadmin/user/index.html,在删除按钮的操作上,把url渲染进去

 <button type="button" onclick="doDel('{% url 'myadmin_user_delete' vo.id %}')" class="btn btn-danger btn-xs">
 <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> 删除</button>

33.在templates/myadmin/base.html中加入删除成功后的提示信息

 <script type="text/javascript">
    function doDel(url){
    Modal.confirm({
        msg: "确定要删除吗?",
        title: ' 信息提示',
        btnok: '确定',
        btncl:'取消'
      }).on(function (e){
        if(e){
            window.location.href=url;
        }
      });
    }

34.即可在页面上删除成功操作

35.编辑修改操作;封装edit和update方法;

def edit(request,uid=0):
    '''执行添加'''
    try:
        ob = User.objects.get(id=uid)
        context = {"user": ob}
        return render(request, "myadmin/user/edit.html", context)
    except Exception as err:
        print(err)
        context = {"info": "没有找到要修改的信息"}
        return render(request, "myadmin/info.html", context)

def update(request,uid):
    '''执行添加'''
    try:
        ob = User.objects.get(id=uid)
        ob.status = request.POST['status']
        ob.nickname = request.POST['nickname']
        ob.update_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        ob.save()
        context = {"info": "修改成功!"}
    except Exception as err:
        print(err)
        context = {"info": "修改失败!"}
    return render(request, "myadmin/info.html", context)

36.新增templates/user/edit.html页面(复制add.html再修改即可)

37.修改index.html中编辑的跳转链接

           <a type="button" href="{% url 'myadmin_user_edit' vo.id %}" class="btn btn-success btn-xs">
              <span class="glyphicon glyphicon-edit" aria-hidden="true"></span> 编辑</a>

38.增删改查即完成操作

39.项目实战之后台管理员登陆与退出,会使用到Django框架中的session,而session信息又存放的数据库中,所以要先使用数据迁移命令在MySQL数据库中先生成一些Django默认自带表。 python manage.py migrate

40.添加中间件,此中间件对后台网址访问做了是否登录的判断,只要访问的URL地址是以 “/admin” 开头的都会执行是否登录判断验证

41.在myadmin应用中创建中间件,创建文件:myobject/myadmin/shopmiddleware.py

# 自定义中间件类
from django.shortcuts import redirect
from django.urls import reverse

import re

class ShopMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.
        print("ShopMiddleware")

    def __call__(self, request):

        # 获取当前请求路径
        path = request.path
        #print("mycall..."+path)

        # 后台请求路由判断
        # 定义网站后台不用登录也可访问的路由url
        urllist = ['/myadmin/login','/myadmin/dologin','/myadmin/logout','/myadmin/verify']
        # 判断当前请求是否是访问网站后台,并且path不在urllist中
        if re.match(r"^/myadmin",path) and (path not in urllist):
            # 判断当前用户是否没有登录
            if "adminuser" not in request.session:
                # 执行登录界面跳转
                return redirect(reverse('myadmin_login'))


        # 请求继续执行下去
        response = self.get_response(request)
        # Code to be executed for each request/response after
        # the view is called.
        return response

42.将自定义的中间件注册到项目中,编辑 myobject/settings.py 配置文件,添加代码

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'myadmin.shopmiddleware.ShopMiddleware',     #注册中间件
]

43.配置路由、模板并测试中间件;配置路由 myobject/myadmin/urls.py 加入如下代码

  # 后台管理员路由
    path('login', index.login, name="myadmin_login"),
    path('dologin', index.dologin, name="myadmin_dologin"),
    path('logout', index.logout, name="myadmin_logout"),

44.编写视图 myobject/myadmin/views/index.py文件 并加入如下代码

# ==============后台管理员操作====================
# 会员登录表单
def login(request):
    return render(request,'myadmin/index/login.html')

# 会员执行登录
def dologin(request):
    pass

# 会员退出
def logout(request):
    pass

45.创建登录模板文件: templates/myadmin/index/login.html 代码如下

{% load static from static%}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>后台管理登录界面</title>
  <!-- 支持响应式布局 -->
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
  <link rel="stylesheet" href="{% static 'myadmin/bower_components/bootstrap/dist/css/bootstrap.min.css' %}">
  <!-- 象形字体 -->
  <link rel="stylesheet" href="{% static 'myadmin/bower_components/font-awesome/css/font-awesome.min.css' %}">
  <!-- 图标 -->
  <link rel="stylesheet" href="{% static 'myadmin/bower_components/Ionicons/css/ionicons.min.css' %}">
  <!-- 主题风格样式 -->
  <link rel="stylesheet" href="{% static 'myadmin/dist/css/AdminLTE.min.css' %}">
  <!-- AdminLTE 皮肤.这里选择的是skin-blue样式,我们还可以有其他皮肤可以选择. -->
  <link rel="stylesheet" href="{% static 'myadmin/dist/css/skins/skin-blue.min.css' %}">
  <!-- 兼容IE9以下浏览器 -->
  <!--[if lt IE 9]>
  <script src="{% static 'myadmin/local/js/html5shiv.min.js' %}"></script>
  <script src="{% static 'myadmin/local/js/respond.min.js' %}"></script>
  <![endif]-->
  <!-- Google Font -->
  <link rel="stylesheet" href="{% static 'myadmin/local/css/google_fonts.css' %}">
</head>
<body class="hold-transition login-page">
<div class="login-box">
  <div class="login-logo">
    <a href="index2.html"><b>餐饮系统后台管理</b></a>
  </div>
  <!-- /.login-logo -->
  <div class="login-box-body">
    <p class="login-box-msg" style="color:red">登录账号或密码错误!</p>

    <form action="index2.html" method="post">
      <div class="form-group has-feedback">
        <input type="text" class="form-control" placeholder="账号">
        <span class="glyphicon glyphicon-user form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="password" class="form-control" placeholder="密码">
        <span class="glyphicon glyphicon-lock form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="text" class="form-control" style="width:150px" placeholder="验证码">
        <span class="form-control-feedback" style="width:150px">
            <img src="{% static 'myadmin/dist/img/verify.png' %}"/>
        </span>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button type="submit" class="btn btn-primary btn-block btn-flat">登录</button>
        </div>
        <!-- /.col -->
      </div>
    </form>

  </div>
  <!-- /.login-box-body -->
</div>
<!-- /.login-box -->

<!-- jQuery 3 -->
<script src="{% static 'myadmin/bower_components/jquery/dist/jquery.min.js' %}"></script>
<!-- Bootstrap 3.3.7 -->
<script src="{% static 'myadmin/bower_components/bootstrap/dist/js/bootstrap.min.js' %}"></script>
</body>
</html>

46.启动服务测试,网站后台就进不去了,统一调跳转登录页面中
47.登录与退出;配置路由 myobject/myadmin/urls.py 加入如下代码 (步骤43已加,可忽悠)

  # 后台管理员路由
    path('login', index.login, name="myadmin_login"),
    path('dologin', index.dologin, name="myadmin_dologin"),
    path('logout', index.logout, name="myadmin_logout"),

48.编写视图文件,编写视图 myobject/myadmin/views/index.py文件 并加入如下代码

from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
from myadmin.models import User

# ==============后台管理员操作====================
def login(request):
    '''加载登录页面'''
    return render(request,"myadmin/index/login.html")

def dologin(request):
    '''执行登录'''
    try:
        #根据登录账号获取用户信息
        user = User.objects.get(username=request.POST['username'])
        # 校验当前用户状态是否是管理员
        if user.status == 6:
            #获取密码并md5
            import hashlib
            md5 = hashlib.md5()
            n = user.password_salt
            s = request.POST['pass']+str(n) 
            md5.update(s.encode('utf-8'))
            # 校验密码是否正确
            if user.password_hash == md5.hexdigest():
                # 将当前登录成功用户信息以adminuser这个key放入到session中
                request.session['adminuser']=user.toDict()
                return redirect(reverse('myadmin_index'))
            else:
                context={"info":"登录密码错误!"}
        else:
            context={"info":"此用户非后台管理账号!"}
    except Exception as err:
        print(err)
        context={"info":"登录账号不存在!"}
    return render(request,"myadmin/index/login.html",context)

def logout(request):
    '''执行退出'''
    del request.session['adminuser']
    return redirect(reverse('myadmin_login'))

49.创建登录模板文件: templates/myadmin/index/login.html 代码如下

{% load static from static %}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>后台管理登录界面</title>
  <!-- 支持响应式布局 -->
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
  <link rel="stylesheet" href="{% static 'myadmin/bower_components/bootstrap/dist/css/bootstrap.min.css' %}">
  <!-- 象形字体 -->
  <link rel="stylesheet" href="{% static 'myadmin/bower_components/font-awesome/css/font-awesome.min.css' %}">
  <!-- 图标 -->
  <link rel="stylesheet" href="{% static 'myadmin/bower_components/Ionicons/css/ionicons.min.css' %}">
  <!-- 主题风格样式 -->
  <link rel="stylesheet" href="{% static 'myadmin/dist/css/AdminLTE.min.css' %}">
  <!-- AdminLTE 皮肤.这里选择的是skin-blue样式,我们还可以有其他皮肤可以选择. -->
  <link rel="stylesheet" href="{% static 'myadmin/dist/css/skins/skin-blue.min.css' %}">
  <!-- 兼容IE9以下浏览器 -->
  <!--[if lt IE 9]>
  <script src="{% static 'myadmin/local/js/html5shiv.min.js' %}"></script>
  <script src="{% static 'myadmin/local/js/respond.min.js' %}"></script>
  <![endif]-->
  <!-- Google Font -->
  <link rel="stylesheet" href="{% static 'myadmin/local/css/google_fonts.css' %}">
</head>
<body class="hold-transition login-page">
<div class="login-box">
  <div class="login-logo">
    <a href="index2.html"><b>餐饮系统后台管理</b></a>
  </div>
  <!-- /.login-logo -->
  <div class="login-box-body">
    <p class="login-box-msg" style="color:red">{{ info }}</p>
    <form action="{% url 'myadmin_dologin' %}" method="post">
      {% csrf_token %}
      <div class="form-group has-feedback">
        <input type="text" name="username" class="form-control" placeholder="账号">
        <span class="glyphicon glyphicon-user form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="password" name="pass"  class="form-control" placeholder="密码">
        <span class="glyphicon glyphicon-lock form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="text" name="code" style="display:inline;width:170px;" class="form-control"  placeholder="验证码">
           <img src="{% static 'myadmin/dist/img/verify.png' %}"/>
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button type="submit" class="btn btn-primary btn-block btn-flat">登录</button>
        </div>
        <!-- /.col -->
      </div>
    </form>

  </div>
  <!-- /.login-box-body -->
</div>
<!-- /.login-box -->

<!-- jQuery 3 -->
<script src="{% static 'myadmin/bower_components/jquery/dist/jquery.min.js' %}"></script>
<!-- Bootstrap 3.3.7 -->
<script src="{% static 'myadmin/bower_components/bootstrap/dist/js/bootstrap.min.js' %}"></script>
</body>
</html>

50.修改模板文件:templates/myadmin/base.html 代码如下,代码在页头处,155行左右

<ul class="dropdown-menu">
  <!-- The user image in the menu -->
  <li class="user-header">
    <img src="{% static 'myadmin/dist/img/user2-160x160.jpg'%}" class="img-circle" alt="User Image">

    <p>
      {{request.session.adminuser.nickname}} - 管理员
      <small>{{ request.session.adminuser.create_at }}加入</small>
    </p>
  </li>
  <!-- Menu Footer-->
  <li class="user-footer">
    <div class="pull-left">
      <a href="#" class="btn btn-default btn-flat">个人信息</a>
    </div>
    <div class="pull-right">
      <a href="{% url 'myadmin_logout' %}" class="btn btn-default btn-flat">退 出</a>
    </div>
  </li>
</ul>

51.启动服务测试,即可测试网站后台是否可以使用。注意只有管理员才开登录
52.在后台登录处添加验证码,配置路由 myobject/myadmin/urls.py 加入如下代码

# 后台管理员路由
    path('login', index.login, name="myadmin_login"),
    path('dologin', index.dologin, name="myadmin_dologin"),
    path('logout', index.logout, name="myadmin_logout"),
    path('verify', index.verify, name="myadmin_verify"), #验证码

53.编写视图 myobject/myadmin/views/index.py文件 并加入如下代码,在后台管理员操作中添加输出验证码方法 verify(),将字体文件STXIHEI.TTF复制到 static/目录下

# ==============后台管理员操作====================
# 会员登录表单
def verify(request):
    #引入随机函数模块
    import random
    from PIL import Image, ImageDraw, ImageFont
    #定义变量,用于画面的背景色、宽、高
    #bgcolor = (random.randrange(20, 100), random.randrange(
    #    20, 100),100)
    bgcolor = (242,164,247)
    width = 100
    height = 25
    #创建画面对象
    im = Image.new('RGB', (width, height), bgcolor)
    #创建画笔对象
    draw = ImageDraw.Draw(im)
    #调用画笔的point()函数绘制噪点
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    #定义验证码的备选值
    #str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
    str1 = '0123456789'
    #随机选取4个值作为验证码
    rand_str = ''
    for i in range(0, 4):
        rand_str += str1[random.randrange(0, len(str1))]
    #构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”
    font = ImageFont.truetype('static/arial.ttf', 21)
    #font = ImageFont.load_default().font
    #构造字体颜色
    fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
    #绘制4个字
    draw.text((5, -3), rand_str[0], font=font, fill=fontcolor)
    draw.text((25, -3), rand_str[1], font=font, fill=fontcolor)
    draw.text((50, -3), rand_str[2], font=font, fill=fontcolor)
    draw.text((75, -3), rand_str[3], font=font, fill=fontcolor)
    #释放画笔
    del draw
    #存入session,用于做进一步验证
    request.session['verifycode'] = rand_str
    """
    python2的为
    # 内存文件操作
    import cStringIO
    buf = cStringIO.StringIO()
    """
    # 内存文件操作-->此方法为python3的
    import io
    buf = io.BytesIO()
    #将图片保存在内存中,文件类型为png
    im.save(buf, 'png')
    #将内存中的图片数据返回给客户端,MIME类型为图片png
    return HttpResponse(buf.getvalue(), 'image/png')

54.在中间件设置放行,编写:myobject/common/shopmiddleware.py文件,在 call()方法的 urllist 变量中加入:/myadmin/verify

 # 定义网站后台不用登录也可访问的路由url
    urllist = ['/myadmin/login','/myadmin/dologin','/myadmin/logout','/myadmin/verify']

55.在登录模板中使用验证码,登录模板文件: templates/myadmin/index/login.html 中加入代码如下

  <p class="login-box-msg" style="color:red">{{ info }}</p>
    <form action="{% url 'myadmin_dologin' %}" method="post">
      {% csrf_token %}
      <div class="form-group has-feedback">
        <input type="text" name="username" class="form-control" placeholder="账号">
        <span class="glyphicon glyphicon-user form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="password" name="pass"  class="form-control" placeholder="密码">
        <span class="glyphicon glyphicon-lock form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input type="text" name="code" style="display:inline;width:170px;" class="form-control"  placeholder="验证码">
           <img src="{% url 'myadmin_verify'%}" onclick="this.src='{% url 'myadmin_verify' %}?sn='+Math.random()" style="float:right;margin:5px 20px;" />
      </div>
      <div class="row">
        <div class="col-xs-12">
          <button type="submit" class="btn btn-primary btn-block btn-flat">登录</button>
        </div>
        <!-- /.col -->
      </div>
    </form>

56.验证码校验,编辑视图文件:myobject/myadmin/views/index.py文件,在视图文件中的会员执行登录方法 dologin() 中加入验证代码

# 会员执行登录
def dologin(request):
    '''执行登录'''
    #验证判断
    verifycode = request.session['verifycode']
    code = request.POST['code']
    if verifycode != code:
        context = {'info':'验证码错误!'}
        return render(request,"myadmin/index/login.html",context)

    try:
        #根据登录账号获取用户信息
        user = User.objects.get(username=request.POST['username'])
        # 校验当前用户状态是否是管理员
        if user.status == 6:
            #获取密码并md5
            import hashlib
            md5 = hashlib.md5()
            n = user.password_salt
            s = request.POST['pass']+str(n) 
            md5.update(s.encode('utf-8'))
            # 校验密码是否正确
            if user.password_hash == md5.hexdigest():
                # 将当前登录成功用户信息以adminuser这个key放入到session中
                request.session['adminuser']=user.toDict()
                return redirect(reverse('myadmin_index'))
            else:
                context={"info":"登录密码错误!"}
        else:
            context={"info":"此用户非后台管理账号!"}
    except Exception as err:
        print(err)
        context={"info":"登录账号不存在!"}
    return render(request,"myadmin/index/login.html",context)

57.启动服务测试,即可测试网站后台是否可以使用。注意只有管理员才开登录

58.后台店铺信息管理;在数据库 osdb 中创建 shop 表

CREATE TABLE `category` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '菜品分类id',
  `shop_id` int(11) DEFAULT NULL COMMENT '店铺id',
  `name` varchar(50) DEFAULT NULL COMMENT '分类名称',
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态:1正常 9删除',
  `create_at` datetime DEFAULT NULL COMMENT '添加时间',
  `update_at` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

59.定义模型Model类;进入myadmin应用目录中编辑:myobject/myadmin/models.py 模型文件

#店铺信息模型
class Shop(models.Model):
    name = models.CharField(max_length=255)        #店铺名称
    cover_pic = models.CharField(max_length=255)#封面图片
    banner_pic = models.CharField(max_length=255)#图标Logo
    address = models.CharField(max_length=255)    #店铺地址
    phone = models.CharField(max_length=255)    #联系电话
    status = models.IntegerField(default=1)        #状态:1正常/2暂停/9删除
    create_at = models.DateTimeField(default=datetime.now)    #创建时间
    update_at = models.DateTimeField(default=datetime.now)    #修改时间

    def toDict(self):
        shopname = self.name.split("-")
        return {'id':self.id,'name':shopname[0],'shop':shopname[1],'cover_pic':self.cover_pic,'banner_pic':self.banner_pic,'address':self.address,'phone':self.phone,'status':self.status,'create_at':self.create_at.strftime('%Y-%m-%d %H:%M:%S'),'update_at':self.update_at.strftime('%Y-%m-%d %H:%M:%S')}

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

60.项目urls路由信息配置;打开根路由文件:myobject/myadmin/urls.py路由文件,编辑路由配置信息

from django.urls import path

from myadmin.views import index
from myadmin.views import user
from myadmin.views import shop

urlpatterns = [
    ...

    #店铺路由
    path('shop/<int:pIndex>', shop.index, name="myadmin_shop_index"),
    path('shop/add', shop.add, name="myadmin_shop_add"),
    path('shop/insert', shop.insert, name="myadmin_shop_insert"),
    path('shop/del/<int:sid>', shop.delete, name="myadmin_shop_del"),
    path('shop/edit/<int:sid>', shop.edit, name="myadmin_shop_edit"),
    path('shop/update/<int:sid>', shop.update, name="myadmin_shop_update"),

    ...
]

61.编辑视图文件;新建视图文件:myobject/myadmin/views/shop.py 视图文件,并进行编辑

62.编写模板文件;打开父类模板:/templates/myadmin/base.html ,编辑导航栏代码

<!-- 导航列表,你可以自行更改图标 -->
<li class="active"><a href="{% url 'myadmin_index' %}"><i class="fa fa-home"></i> <span>首页</span></a></li>
<li><a href="{% url 'myadmin_user_index' 1 %}"><i class="fa fa-users"></i> <span>员工管理</span></a></li>
<li><a href="{% url 'myadmin_shop_index' 1 %}"><i class="fa fa-sitemap"></i> <span>店铺管理</span></a></li>

63.后台店铺信息浏览页模板:/templates/myadmin/shop/index.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 class="box-tools">
                <div class="input-group input-group-sm" style="width: 150px;">
                  <input type="text" name="table_search" 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>
              </div>
            </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>操作</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 == 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="doDelete('{% url 'myadmin_category_del' vo.id %}')" class="btn btn-danger btn-xs">
                      <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> 删除</button>
                    <a href="#" class="btn btn-warning btn-xs">
                      <span class="glyphicon glyphicon-search" aria-hidden="true"></span> 查看菜品</a>
                  </td>
                </tr>
                {% endfor %}
              </table>
            </div>
            <!-- /.box-body -->
            <div class="box-footer clearfix">
              <a role="button" href="{% url 'myadmin_category_add' %}" class="btn btn-primary">
                <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> 添加菜品分类</a>
                <ul class="pagination pagination-sm no-margin pull-right">
                    <li><a href="{% url 'myadmin_category_index' pIndex|add:-1 %}?{{mywhere|join:'&'}}">&laquo;</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:'&'}}">&raquo;</a></li>
                </ul>
            </div>
          </div>
          <!-- /.box -->
        </div>
      </div>

    </section>
    <!-- /.content -->
{% endblock %}

64.后台店铺信息添加表单页模板:/templates/myadmin/shop/add.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">
                <h2 class="box-title"><span class="glyphicon glyphicon-calendar" aria-hidden="true">添加菜品分类信息</h2>
            </div>
            <!-- /.box-header -->
            <!-- form start -->
            <form class="form-horizontal" action="{% url 'myadmin_category_insert' %}" method="post">
                {% csrf_token %}
              <div class="box-body">
                <div class="form-group">
                  <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>
                </div>
                <div class="form-group">
                  <label for="inputEmail3" class="col-sm-2 control-label">类别名称:</label>

                  <div class="col-sm-4">
                    <input type="text" name="name" class="form-control" id="inputText2" placeholder="类别名称" />
                  </div>
                </div>
              </div>
              <!-- /.box-body -->
              <div class="box-footer">
                <div class="col-sm-offset-2 col-sm-10">
                  <button type="submit" class="btn btn-primary">提交</button> &nbsp; 
                  <button type="reset" class="btn btn-default">重置</button>
                <div class="col-sm-offset-2 col-sm-10">
              </div>
              <!-- /.box-footer -->
            </form>
          </div>
          <!-- /.box -->
        </div>
      </div>

    </section>
    <!-- /.content -->
{% endblock %}

65.后台店铺信息编辑模板:/templates/myadmin/shop/edit.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">
                <h2 class="box-title"><span class="glyphicon glyphicon-calendar" aria-hidden="true">编辑菜品分类信息</h2>
            </div>
            <!-- /.box-header -->
            <!-- form start -->
            <form class="form-horizontal" action="{% url 'myadmin_category_update' category.id  %}" method="post">
                {% csrf_token %}
              <div class="box-body">
                <div class="form-group">
                  <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 }}" {% if category.shop_id == svo.id %}selected{% endif %} >{{ svo.name }}</option>
                      {% endfor %}
                    </select>
                  </div>
                </div>
                <div class="form-group">
                  <label for="inputEmail3" class="col-sm-2 control-label">类别名称:</label>

                  <div class="col-sm-4">
                    <input type="text" name="name" value="{{ category.name }}" class="form-control" id="inputText2" placeholder="类别名称" />
                  </div>
                </div>
              </div>
              <!-- /.box-body -->
              <div class="box-footer">
                <div class="col-sm-offset-2 col-sm-10">
                  <button type="submit" class="btn btn-primary">保存</button> &nbsp; 
                  <button type="reset" class="btn btn-default">重置</button>
                <div class="col-sm-offset-2 col-sm-10">
              </div>
              <!-- /.box-footer -->
            </form>
          </div>
          <!-- /.box -->
        </div>
      </div>

    </section>
    <!-- /.content -->
{% endblock %}

66.在项目根目录下启动服务,并使用浏览器访问测试
(看到个bug,修改操作,重新上传店铺图片和logo没有保存到数据)

67.项目实战之后台菜品类别信息管理

项目实战之后台菜品信息管理

项目实战之后台会员信息管理