Django开发员工管理系统(Part I)

2023-11-11

在上一章中介绍了如何配置Django框架等以及一些注意细节,俗话说:“配置好项目的环境相当于完成了整个项目的80%”,如果还有没配好Django框架的,可以先看看前面的这篇文章:走进Django框架。

1. 准备工作

1.1 创建django项目

  • 管理员模式打开cmd。
  • 使用cd命令定位到要保存项目的文件夹。eg:cd py_code\PycharmProjects。
  • 输入django-admin startproject 创建项目名称 的格式就可以创建出django项目。eg: django-admin startproject mysite。

1.2 创建app

在pycharm终端进行添加app(功能模块),输入格式:python manage.py startapp app名称。eg:python manage.py startapp webapp

1.3 配置settings.py文件,完成app注册

请添加图片描述

2. 设计数据库表结构

在这个项目中我们可以包含的表有:部门表和员工表。

  • 在部门表中我们需要有部门的名称和部门的ID,而其中的ID我们是可以直接使用django中创建表里面的自增ID的,所以部门表的这个类我们就可以这样写:

    •   class Department(models.Model):
            """ 部门表 """
            title = models.CharField(verbose_name="标题", max_length=32)
      
  • 在员工表中我们则需要员工的名字、密码、年龄、账户余额、创建时间等(这些都是普通正常创建即可)。

    •   	name = models.CharField(verbose_name="姓名", max_length=16)
            password = models.CharField(verbose_name="密码", max_length=64)
            age = models.IntegerField(verbose_name="年龄")
            accout = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
            create_time = models.DateTimeField(verbose_name="创建时间")
      
  • 员工表中还可以有员工性别,这时候我们可以使用django中的约束,将1代表成男,2代表成女,即可以写成下面这样:

    •       gender_choices = (
                (1, "男"),
                (2, "女"),
            )
            gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
      
  • 除此之外,员工表中还必须有员工对应的部门,我们这里使用的是django自动约束,将其与上面的部门表关联起来,具体的写法是这样的:

    •       # django自动约束
            # to表示与哪张表关联 to_field表示与表中的哪一列关联
            # 此处写的depart其实django会自动生成数据列depart_id
            # 部门表删除的两种解决方案
            # 1.级联删除
            depart = models.ForeignKey(to="Department", to_field="id")
      
  • 但是上面这样写又有一点缺陷,那就是在删除部门表中的某一个部门(某一列)之后,员工表中的某一些员工上的depart_id可能就会在父表(部门表)中查找不到,而这里有两种常见的解决方法:1. 级联删除:当父表中的一条记录被删除,子表中关联的记录也会对应的自己主动删除;2. 置空处理:当父表中的一条记录被删除后,子表中关联的记录的那一列会自动置为空值。

    •       # 1.级联删除
            depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
            # 2.置空
            depart = models.ForeignKey(to="Department", to_field="id", null=True, blank=True, on_delete=models.SET_NULL)
      

最终在models.py文件中写出来的全部代码如下:

class Department(models.Model):
    """ 部门表 """
    title = models.CharField(verbose_name="标题", max_length=32)

class UserInfo(models.Model):
    """ 员工表 """
    name = models.CharField(verbose_name="姓名", max_length=16)
    password = models.CharField(verbose_name="密码", max_length=64)
    age = models.IntegerField(verbose_name="年龄")
    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)
    accout = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
    create_time = models.DateTimeField(verbose_name="创建时间")
    depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)

3. 在MySQL中生成表

3.1 创建数据库

输入:create database employeeManagement_system default charset utf8 collate utf8_general_ci;

3.2 修改配置文件,连接MySQL数据库

由于django默认使用的数据库是sqlite,而我们现在使用的是MySQL数据库,所以我们就需要在settings.py文件里面修改一下配置。

注释掉原来的DATABASES,修改成下面这一段:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'employeeManagement_system', # 刚才创建数据库的名字
        'USER': 'root',
        'PASSWORD': '123456', # 自己数据库的密码
        'HOST': '127.0.0.1', # 安装MySQL的机器(默认这里都是主机安装)
        'PORT': '3306', # 设置端口号(默认3306)
    }
}

3.3 通过django命令生成数据库表

在pycharm终端输入命令(依次输入):

python manage.py makemigrations
python manage.py migrate

之后在MySQL之后查看验证有这两个表即说明生成成功:

请添加图片描述

4. 编写部门列表

对于一些前段的样式,这里推荐一个网站:https://v3.bootcss.com/components

4.1 (前段页面)准备工作

在编写前段页面之前需要导入两样东西:jQuery和bootstrap。

4.1.1 jQuery

在浏览器打开网页:https://code.jquery.com/jquery-3.6.0.min.js,Ctrl+s将整个文件下载下来。将下载下来的整个文件放在static下的js文件夹中。

请添加图片描述

4.1.2 bootstrap

在浏览器打开网页:https://v3.bootcss.com/getting-started/#download,下载用于生产环境的 Bootstrap。将下载下来的整个文件夹放在static下的plugins文件夹中。

请添加图片描述

4.2 编写前段代码

本系列注重的是django开发,因此前端代码直接给出。

{% load static %}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <style>
      .navbar{
        border-radius: 0;
      }
    </style>
</head>
<body>
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">员工管理系统</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li><a href="/depart/list/">部门管理</a></li>
        <li><a href="#">Link</a></li>
      </ul>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">登录</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">个人资料</a></li>
            <li><a href="#">设置</a></li>
            <li><a href="#">其他</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">注销</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

<div>
  <div class="container">
    <div style="margin-bottom: 10px">
      <a class="btn btn-success" href="#">
        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
        新建部门
      </a>
    </div>
    
    <div class="panel panel-default">
      <!-- Default panel contents -->
      <div class="panel-heading">
        <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
        部门列表
      </div>

      <!-- Table -->
      <table class="table table-bordered">
        <thead>
          <tr>
            <th>ID</th>
            <th>部门名称</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <th>1</th>
            <td>销售部</td>
            <td>
              <a class="btn btn-primary btn-xs">编辑</a>
              <a class="btn btn-danger btn-xs">删除</a>
            </td>
          </tr>
        </tbody>
      </table>
    </div>

  </div>
</div>

<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</body>
</html>

页面显示:

请添加图片描述

4.3 实现部门具体功能

4.3.1 查找数据库

请添加图片描述

当数据库中有数据的时候,我们就需要将这些数据加载到页面上,这对应到上一章中总结的django对表中数据的查操作。

# 去数据库中获取所有部门列表(查)
    data_list = models.Department.objects.all()

    return render(request, 'depart_list.html', {'data_list': data_list})

在前端代码中进行遍历显示。

{% for obj in data_list %}
            <tr>
              <th>{{ obj.id }}</th>
              <td>{{ obj.title }}</td>
              <td>
                <a class="btn btn-primary btn-xs">编辑</a>
                <a class="btn btn-danger btn-xs">删除</a>
              </td>
            </tr>
          {% endfor %}

请添加图片描述

4.3.2 新增部门

前端页面:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新建部门</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <style>
      .navbar{
        border-radius: 0;
      }
    </style>
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
          <!-- Brand and toggle get grouped for better mobile display -->
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
              <span class="sr-only">Toggle navigation</span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">员工管理系统</a>
          </div>
      
          <!-- Collect the nav links, forms, and other content for toggling -->
          <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
              <li><a href="/depart/list/">部门管理</a></li>
              <li><a href="#">Link</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
              <li><a href="#">登录</a></li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a>
                <ul class="dropdown-menu">
                  <li><a href="#">个人资料</a></li>
                  <li><a href="#">设置</a></li>
                  <li><a href="#">其他</a></li>
                  <li role="separator" class="divider"></li>
                  <li><a href="#">注销</a></li>
                </ul>
              </li>
            </ul>
          </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
      </nav>
    
    <div>
        <div class="container">
            <div class="panel panel-default">
                <div class="panel-heading">
                  <h3 class="panel-title">新建部门</h3>
                </div>
                <div class="panel-body">
                    <form method="post">
                        {% csrf_token %}
                        <div class="form-group">
                            <label>部门名称</label>
                            <input type="text" class="form-control" placeholder="部门名称" name="title" />
                        </div>
                        <button type="submit" class="btn btn-primary">保 存</button>
                      </form>
                </div>
              </div>
        </div>
    </div>
    
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    <script src="{% static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</body>
</html>

逻辑代码:显示页面是get请求,提交操作是post请求。

def depart_add(request):
    """添加部门"""
    if request.method == 'GET':
        return render(request, 'depart_add.html')
    title = request.POST.get("title")
    models.Department.objects.create(title=title)
    return redirect("/depart/list/")

4.3.3 删除部门

删除功能是比较简单的,通过id来删除数据库中的数据。

前端代码:

<a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除</a>

逻辑代码:

def depart_delete(request):
    """ 删除部门 """
    nid = request.GET.get('nid')
    models.Department.objects.filter(id=nid).delete()
    return redirect("/depart/list/")

4.3.4 修改部门

在url中我们可以使用正则表达式的形式来编写,以后获取id也是通过这里的nid进行获取的:path('depart/<int:nid>/edit/', views.depart_edit)

前端代码:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新建部门</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
    <style>
      .navbar{
        border-radius: 0;
      }
    </style>
</head>
<body>
    <nav class="navbar navbar-default">
        <div class="container-fluid">
          <!-- Brand and toggle get grouped for better mobile display -->
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
              <span class="sr-only">Toggle navigation</span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">员工管理系统</a>
          </div>
      
          <!-- Collect the nav links, forms, and other content for toggling -->
          <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
              <li><a href="/depart/list/">部门管理</a></li>
              <li><a href="#">Link</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
              <li><a href="#">登录</a></li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a>
                <ul class="dropdown-menu">
                  <li><a href="#">个人资料</a></li>
                  <li><a href="#">设置</a></li>
                  <li><a href="#">其他</a></li>
                  <li role="separator" class="divider"></li>
                  <li><a href="#">注销</a></li>
                </ul>
              </li>
            </ul>
          </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
      </nav>
    
    <div>
        <div class="container">
            <div class="panel panel-default">
                <div class="panel-heading">
                  <h3 class="panel-title">修改部门</h3>
                </div>
                <div class="panel-body">
                    <form method="post">
                        {% csrf_token %}
                        <div class="form-group">
                            <label>部门名称</label>
                            <input type="text" class="form-control" placeholder="部门名称" name="title" value="{{ row_object.title }}" />
                        </div>
                        <button type="submit" class="btn btn-primary">保 存</button>
                      </form>
                </div>
              </div>
        </div>
    </div>
    
    <script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
    <script src="{% static 'plugins/bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</body>
</html>

逻辑代码:

def depart_edit(request, nid):
    """ 修改部门 """
    if request.method == "GET":
        row_object = models.Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"row_object": row_object})
    title = request.POST.get("title")
    models.Department.objects.filter(id=nid).update(title=title)
    return redirect("/depart/list/")

5. 模板的继承

在上面的前段代码中会发现一个问题:模板的重复性非常高,那么我们可以对这些模板进行提取吗?

答案是可以的。在django中是支持模板继承的,格式如下:

在模板的前面写上众多模板的共同点...

    <div>
        {% block content %}{% endblock %}
    </div>
    
在模板的后面写上众多模板的共同点...

注意:中间的{% block content %}{% endblock %}就是继承模板中不一样的部分,只需要在继承模板中写下这个骨架:

{% extends 'layout.html' %}
{% block content %}
	...
{% endblock %}

在骨架的中间(省略号部分)写下每一个继承模板独有的点即可,其他前面或者后面部分的内容都会去被继承的模板中调用。

6. 实现员工具体功能

6.1 查找数据库

先在员工表中添加一行数据:

请添加图片描述

前段代码:这里使用模板继承。

{% extends 'layout.html' %}

{% block content %}
<div class="container">
  <div style="margin-bottom: 10px">
    <a class="btn btn-success" href="#">
      <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
      新增员工
    </a>
  </div>
  
  <div class="panel panel-default">
    <!-- Default panel contents -->
    <div class="panel-heading">
      <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
      员工列表
    </div>

    <!-- Table -->
    <table class="table table-bordered">
      <thead>
        <tr>
          <th>ID</th>
          <th>姓名</th>
          <th>密码</th>
          <th>年龄</th>
          <th>账户余额</th>
          <th>入职时间</th>
          <th>性别</th>
          <th>所属部门</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        {% for obj in data_list %}
          <tr>
            <th>{{ obj.id }}</th>
            <td>{{ obj.name }}</td>
            <td>{{ obj.password }}</td>
            <td>{{ obj.age }}</td>
            <td>{{ obj.account }}</td>
            <td>{{ obj.create_time|date:"Y-m-d" }}</td>
            <td>{{ obj.get_gender_display }}</td>
            <td>{{ obj.depart.title }}</td>
            <td>
              <a class="btn btn-primary btn-xs" href="#">编辑</a>
              <a class="btn btn-danger btn-xs" href="#">删除</a>
            </td>
          </tr>
        {% endfor %}
      </tbody>
    </table>
  </div>
</div>
{% endblock %}

注意:时间转字符串的模板语法(eg:obj.create_time|date:"Y-m-d")、django自动连表操作(eg:obj.depart.title)、django选择约束获取的操作(eg:obj.get_gender_display)。

逻辑代码:

def user_list(request):
    """ 用户列表 """
    data_list = models.UserInfo.objects.all()
    return render(request, 'user_list.html', {"data_list": data_list})

6.2 新增员工

前段代码:

{% extends 'layout.html' %}

{% block content %}
<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
          <h3 class="panel-title">新建员工</h3>
        </div>
        <div class="panel-body">
            <form method="post">
                {% csrf_token %}
                <div class="form-group">
                    <label>姓名</label>
                    <input type="text" class="form-control" placeholder="姓名" name="name" />
                </div>
                <div class="form-group">
                    <label>密码</label>
                    <input type="text" class="form-control" placeholder="密码" name="password" />
                </div>
                <div class="form-group">
                    <label>年龄</label>
                    <input type="text" class="form-control" placeholder="年龄" name="age" />
                </div>
                <div class="form-group">
                    <label>账户余额</label>
                    <input type="text" class="form-control" placeholder="账户余额" name="account" />
                </div>
                <div class="form-group">
                    <label>入职时间</label>
                    <input type="text" class="form-control" placeholder="入职时间" name="create_time" />
                </div>
                <div class="form-group">
                    <label>性别</label>
                    <select class="form-control" name="gender">
                        {% for item in gender_choices %}
                            <option value="{{ item.0 }}">{{ item.1 }}</option>
                        {% endfor %}
                    </select>
                </div>
                <div class="form-group">
                    <label>所属部门</label>
                    <select class="form-control" name="depart">
                        {% for item in depart_list %}
                            <option value="{{ item.id }}">{{ item.title }}</option>
                        {% endfor %}
                    </select>
                </div>
                <button type="submit" class="btn btn-primary">保 存</button>
              </form>
        </div>
      </div>
</div>
{% endblock %}

逻辑代码:

def user_add(request):
    """ 添加用户 """
    if request.method == 'GET':
        context = {
            'gender_choices': models.UserInfo.gender_choices,
            'depart_list': models.Department.objects.all()
        }
        return render(request, 'user_add.html', context)
    name = request.POST.get('name')
    password = request.POST.get('password')
    age = request.POST.get('age')
    account = request.POST.get('account')
    create_time = request.POST.get('create_time')
    gender = request.POST.get('gender')
    depart_id = request.POST.get('depart')
    models.UserInfo.objects.create(name=name,password=password,age=age,
                                   account=account,create_time=create_time,
                                   gender=gender,depart_id=depart_id)
    return redirect("/user/list/")

7. ModelForm的使用

我们在上面进行员工信息录入的时候采用的是最原始的方法,虽然也是可以解决问题,但是代码总体看起来是非常臃肿的,当输入框需要再增加或者减少的时候,势必就会进行一系列的改动,对此,django中就引入了ModelForm插件,这也是比较主流的开发方式,减少了很多工作量。

class UserModelForm(forms.ModelForm):
    class Meta:
        model = models.UserInfo
        fields = ["name","password","age","account","create_time","gender","depart"]

在view.py中写下这类就表示在这个类下引入django中的ModelForm插件,而model = models.UserInfo表示的就是使用models.py的哪个类(这里使用的是员工类),后面写下:fields = ["name","password","age","account","create_time","gender","depart"]表示的就是django会自动帮我们生成这些字段,将这个封装上字段的类传到前端,使用一个简单的循环就可以实现之前普通写法中页面一样的显示功能:

{% for field in form %}
	<div class="form-group">
		<label>{{ field.label }}</label>
		{{ field }}
	</div>
{% endfor %}

前提是需要导入forms包:from django import forms

除此之外,我们还需要在类中定义一个函数(这个函数一定是固定的),在函数中循环使用widget插件,通过这个插件中的attrs就可以指定前段代码的class样式或者placeholder等等。

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label}

这时候会发现一个问题,就是所属部门的下拉框中显示的不是一个一个的部门名称,而是一些类对象,这是因为django中通过部门id去找部门之后返回的形式是去调用__str__函数的,而这个函数默认的返回值就事当前对象,这里我们就需要自己重新写一个__str__函数,并且重新指定其返回值。

class Department(models.Model):
    """ 部门表 """
    title = models.CharField(verbose_name="标题", max_length=32)
    def __str__(self):
        return self.title

以上就可以把整个添加页面很好地显示出来了(总体上与之前写的页面并无区别,但是引入了ModelForm插件使得代码量少了不少,代码的复用程度也提高了)。接下来就是提交数据的功能,在使用插件的情况下,我们提交数据的时候还可以对数据进行校验,如果数据合法就可以存到数据库中,若有数据不合法的情况的话,就会在当前页面上显示错误。

比如django中支持可以直接在引入插件的类中对提交的出入进行一个限制(下面这样就表示了密码只能够是大于6位数的),并且在django中如果不做限制,默认的就是非空,也就是说如果有空没填的话也是会显示错误信息的。

password = forms.CharField(min_length=6, label="密码")

还有一点是数据不合法的时候页面中显示的错误信息是英文的,为了方便用户,我们可以手动在settings.py文件中修改显示语言配置:

# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'

将原来的en-us注释掉,修改成zh-hans。

其他的具体看总的代码即可:

前段代码:

{% extends 'layout.html' %}

{% block content %}
<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
          <h3 class="panel-title">新建员工</h3>
        </div>
        <div class="panel-body">
            <form method="post" novalidate>
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label>{{ field.label }}</label>
                        {{ field }}
                        <span style="color: red;">{{ field.errors.0 }}</span>
                    </div>
                {% endfor %}
                <button type="submit" class="btn btn-primary">保 存</button>
              </form>
        </div>
      </div>
</div>
{% endblock %}

逻辑代码:

# 编写ModelFrom类
class UserModelForm(forms.ModelForm):
    password = forms.CharField(min_length=6, label="密码")
    class Meta:
        model = models.UserInfo
        fields = ["name","password","age","account","create_time","gender","depart"]
        # widgets = {
        #     "name": forms.TextInput(attrs={"class": "form-control"})
        # }
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {"class": "form-control", "placeholder": field.label} # 循环找到所有插件,添加"class": "form-control"
def user_model_form_add(request):
    """ 添加用户(ModelFrom版) """
    if request.method == 'GET':
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})
    # 进行数据校验
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法。加入到数据库中
        form.save()
        return redirect('/user/list/')
    # 在页面上显示错误信息
    return render(request, 'user_model_form_add.html', {"form": form})

8. 总结

以上为Django开发员工管理系统的Part I部分,未完待续,请持续关注这个系列。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django开发员工管理系统(Part I) 的相关文章

随机推荐

  • VMware16调整了路径后界面全部变成了英文

    VMware调整了安装的路径后 界面全部变成了英文 查询了messages下的设置没发现问题 依然有zh CN 检查了本机的 区域设置 改回 中国 再启动VM 但是还是英文的 在 控制面板 卸载程序 运行VM后 进行更改 完成后恢复成中文
  • 【基于随机化的非确定性算法】模拟退火学习笔记

    暑假zky学长讲了模拟退火 现在正式来更一发学习笔记 这次不口胡直接正文 gt w lt 线 割 分 是 我 模拟退火 Simulated Annealing 简称SA 是一种通用概率算法 用来在一个大的搜寻空间内找寻命题的最优解 这是小学
  • 给 Android 开发者的 RxJava 详解

    http gank io post 560e15be2dca930e00da1083
  • 软考中级数据库系统工程师备考详细资料

    1 考试介绍 计算机技术与软件专业技术资格 水平 考试 以下简称计算机软件资格考试 是原中国计算机软件专业技术资格和水平考试 简称软件考试 的完善与发展 计算机软件资格考试是由国家人力资源和社会保障部 工业和信息化部领导下的国家级考试 其目
  • 搜索功能测试点汇总

    前提 1 明确搜索入口 2 明确搜索条件 3 明确搜索逻辑 一 界面测试 搜索框UI显示正常 布局合理 搜索框默认的搜索icon 末尾处的X按钮等等 搜索页面布局合理 无错别字 搜索出的结果展示 布局合理 已查看过的结果 是否要做特殊 如置
  • cloudstack guestnetwork vpc ingress/ergess介绍

    cloudstack的advance网络中可以创建的network如下 guestnetwork IsolatedNetwork vpc vpnCustomer gateway 这个应该不算一个网络 只是连接点 1 guestnetwork
  • mac下eclipse配置tomcat

    1 到 apache官方主页 http tomcat apache org 下载 Mac 版本的完整 tar gz文件包 解压拷贝到 Library 目录下 并命名为Tomcat 其他目录也可以 我这就以 Library做讲解 2 打开终端
  • 基于Java API 方式使用Java kafka在IDEA创建依赖

    在idea创建工程Maven 在pom xml添加如下依赖
  • Java编写的图书管理系统,窗体版本-003

    今天为大家分享一个java语言编写的图书管理程序 003 目前系统功能已经很全面 后续会进一步完善 整个系统界面漂亮 有完整得源码 希望大家可以喜欢 喜欢的帮忙点赞和关注 一起编程 一起进步 开发环境 开发语言为Java 开发环境Eclip
  • 数据库第十章——数据库恢复技术

    第十章 数据库恢复技术 文章目录 第十章 数据库恢复技术 一 事务的基本概念 一 基本概念 二 特性 二 数据库恢复概述 三 故障的种类 四 恢复的实现技术 如何建立冗余数据 一 数据转储 二 登记日志文件 五 恢复策略 如何利用冗余数据进
  • ruoyi cloud 用官方自带的工具更换包名出现的问题与解决办法

    使用ruoyi cloud官方的包生成后 有2点的修改很重要 1是所有带META INF spinrg文件夹的org springframework boot autoconfigure AutoConfiguration imports文
  • oracle10g异常日志查看

    oracle10g异常日志查看 警告日志 oracle product 10 2 0 db 1 admin orcl bdump alert orcl log 监听日志 oracle product 10 2 0 db 1 NETWORK
  • SpringMVC:从入门到精通,7篇系列篇带你全面掌握--三.使用SpringMVC完成增删改查

    Welcome Huihui s Code World 接下来看看由辉辉所写的关于SpringMVC的相关操作吧 目录 Welcome Huihui s Code World 效果演示 一 导入项目的相关依赖 二 添加框架的配置文件 gen
  • 高效的公式提取神器Mathpix snipping Tool+ Mathtype

    推荐一个有用高效的公式提取神器Mathpix snipping Tool Mathtype Mathpix snip是一款功能强大 很有用的公式识别及复制软件 能够将已有的PDF或CAJ等文中的公式 纸上打印的公式 甚至在纸上手写的公式统统
  • 共享计算机后防火墙能开启,Windows XP中防火墙后如何实现共享

    通过开启Windows XP系统中内置的 Internet 连接防火墙 可以让我们安心的上网冲浪 但是在开启了 Internet 连接防火墙 之后 我们就会发现不能正常的使用 网络共享 功能了 Internet 连接防火墙 在阻挡恶意程序的
  • C语言将int类型存入char型

    最近在做算法题的时候遇到了一个问题 就是怎么将int类型的值变成当成字符串 字符数组 类型 例如 有个 int 1024 如何将整形的1024转为字符串类型 String 的1024或者字符数组 char 类型的1024呢 其实可以用ito
  • Vscode快速入门、 插件安装、插件位置、修改vscode默认引用插件的路径、在命令行总配置code、快捷键

    Vscode快速入门 这里写目录标题 安装 插件安装 Ctrl Shift X 插件商店 插件位置 默认位置 修改默认路径 修改vscode默认引用插件的路径 在命令行总配置code 基本操作 安装 Visual Studio Code 官
  • RxJava2+Retrofit2+RxLifecycle3+OkHttp3网络请求封装(动态演示)

    入职公司后 公司要求组件化开发 经过讨论后我将网络请求框架单独进行了封装 不过当时框架里将常用的 util 和 ui 均放入到了共同的 Common 包下 导致里面部分代码耦合 后来为了降低耦合性又将 Common 拆分为了lib comm
  • Python 解决百钱买百鸡问题

    我国古代数学家张丘建在 算经 一书中曾提出过著名的 百钱买百鸡 问题 该问题叙述如下 鸡翁一 值钱五 鸡母一 值钱三 鸡雏三 值钱一 百钱买百鸡 则翁 母 雏各几何 翻译过来 意思是公鸡一个五块钱 母鸡一个三块钱 小鸡三个一块钱 现在要用一
  • Django开发员工管理系统(Part I)

    文章目录 1 准备工作 1 1 创建django项目 1 2 创建app 1 3 配置settings py文件 完成app注册 2 设计数据库表结构 3 在MySQL中生成表 3 1 创建数据库 3 2 修改配置文件 连接MySQL数据库