一、新建项目和APP
新建文件夹staff_management
pycharm中创建新项目
终端执行 python -m venv virtual_env(虚拟环境名称) 新建虚拟环境
Windows执行 virtual_env(虚拟环境名)\Scripts\activate 激活虚拟环境
虚拟环境中 pip install django (-i https://pypi.tuna.tsinghua.edu.cn/simple) 如下载失败使用镜像源
虚拟环境执行 django-admin startproject staff_management_01(项目名) . 创建项目
执行 python manage.py migrate 创建数据库
执行 python manage.py startapp manage01(应用名称) 创建应用程序
在项目文件夹(staff_management_01)下settings.py中installed_apps中添加 manage01.apps.Mange01Config 注册应用
二、创建表结构
应用中models.py文件内根据需求设计表结构
from django.db import models
# Create your models here.
class Department(models.Model):
"""部门表结构"""
# verbose_name:备注名称
title = models.CharField(verbose_name='部门标题', max_length=32)
class Employee(models.Model):
"""员工表结构"""
name = models.CharField(verbose_name='姓名', max_length=16)
pwd = models.CharField(verbose_name='密码', max_length=64)
age = models.IntegerField(verbose_name='年龄')
# max_digits:数字位长度
# decimal_places:小数位个数
salary = models.DecimalField(verbose_name='工资', max_digits=10, decimal_places=2, default=0)
entry_name = models.DateTimeField(verbose_name='入职时间')
# 外键约束 to:与哪张表关联 to_field: 与表中哪列关联 on_delete: 级联删除
depart = models.ForeignKey(to='Department', to_field='id', on_delete=models.CASCADE)
# 置空
# depart = models.ForeignKey(to='Department', to_field='id', null=True, blank=True, on_delete=models.SET_NULL)
gender_choices = ((1, "男"), (2, "女"))
# choices: 在指定范围内选择
gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)
三、生成数据库
MySQL中执行 create database staff_management; 创建数据库
修改setting.py中的内容,连接MySQL:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'staff_management',
'USER': 'root',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': 3306,
}
}
通过django生成数据库表:
虚拟环境下须有pymysql及mysqlclient两个包,没有的话先安装
执行
python manage.py makemigrations manage01(APP名称)
python manage.py migrate
四、部门列表
应用目录下新建 templates 和 static 文件夹备用
staff_management_01(项目)文件夹下urls.py文件夹中添加
from django.contrib import admin
from django.urls import path
from manage01 import views
urlpatterns = [
path("admin/", admin.site.urls),
path('department/list', views.depart_list)
]
manage01文件夹下views.py中添加
from django.shortcuts import render
# Create your views here.
def depart_list(request):
"""部门列表"""
return render(request, 'department_list.html')
templates文件夹下创建department_list.html文件(暂时设计大致结构)
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
</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="/department/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 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-primary" href="#">添加</a>
</div>
<div class="bs-example" data-example-id="panel-without-body-with-table">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">部门列表</div>
<!-- Table -->
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>部门名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="{% static 'js/jquery-3.7.0.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>
此时预览网页如下,但是表格内容为提前输入的,并没有从数据库获取:
从数据库获取数据并显示到网页(已提前在数据库中添加了两个数据):
1-获取数据库数据:
from django.shortcuts import render
from manage01 import models
# Create your views here.
def depart_list(request):
"""部门列表"""
dp_list = models.Department.objects.all()
return render(request, 'department_list.html', {"dp_list": dp_list})
2- 在网页显示数据:
<tbody>
{% for obj in dp_list %}
<tr>
<th scope="row">{{ 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 %}
</tbody>
完成后页面如下:
五、跳转-新建部门
左上角“新建部门”设置跳转
<a class="btn btn-primary" href="/department/add" target="_blank">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
新建部门
</a>
编写/department/add页面:
1-添加URL:
from django.contrib import admin
from django.urls import path
from manage01 import views
urlpatterns = [
path("admin/", admin.site.urls),
path('department/list', views.depart_list),
path('department/add', views.depart_add),
]
2-添加views:
def depart_add(request):
"""添加部门"""
if request.method == 'GET':
return render(request, 'department_add.html')
3-编写department_add.html页面:
PS:HTML页面里head、js、nav部门可直接照抄department_list.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加部门</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
</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="/department/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 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 class="form-horizontal" method="post">
{% csrf_token %}
<div class="form-group">
<label class="col-sm-2 control-label">部门名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="标题" name="depart" id="department">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="{% static 'js/jquery-3.7.0.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>
页面如下:
4-获取刚提交的部门名称并重定向回/department/list:
def depart_add(request):
"""添加部门"""
if request.method == 'GET':
return render(request, 'department_add.html')
title = request.POST.get("depart")
models.Department.objects.create(title=title)
return redirect('/department/list')
六、删除部门
1-增加URL
urlpatterns = [
path("admin/", admin.site.urls),
path('department/list/', views.depart_list),
path('department/add/', views.depart_add),
path('department/delete/', views.depart_del),
]
2-修改views.py
def depart_del(request):
"""删除部门"""
nid = request.GET.get('nid')
models.Department.objects.filter(id=nid).delete()
return redirect('/department/list')
在department_list.html下修改“删除”键的链接:
<a class="btn btn-danger btn-xs" href="/department/delete/?nid={{ obj.id }}">删除</a>
七、修改部门
添加URL:
from django.contrib import admin
from django.urls import path
from manage01 import views
urlpatterns = [
path("admin/", admin.site.urls),
path('department/list/', views.depart_list),
path('department/add/', views.depart_add),
path('department/delete/', views.depart_del),
path('department/<int:nid>/edit', views.depart_edit),
]
编写views:
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("depart")
models.Department.objects.filter(id=nid).update(title=title)
return redirect("/department/list")
编写页面:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加部门</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
</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="/department/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 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 class="form-horizontal" method="post">
{% csrf_token %}
<div class="form-group">
<label class="col-sm-2 control-label">部门名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="标题" name="depart" id="department"
value="{{ row_object.title }}">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="{% static 'js/jquery-3.7.0.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>
修改list页面:
<a class="btn btn-primary btn-xs" href="/department/{{ obj.id }}/edit">编辑</a>
八、django中的模板复用
模板HTML中{% block 模板名称 %} {% endblock %}部分为模板外自定义内容
模板复用:
{% extends '模板.html' %}
{% block 模板名称 %}
自定义内容
{% endblock %}
九、员工列表
添加URL:
from django.contrib import admin
from django.urls import path
from manage01 import views
urlpatterns = [
path("admin/", admin.site.urls),
# 部门管理
path('department/list/', views.depart_list),
path('department/add/', views.depart_add),
path('department/delete/', views.depart_del),
path('department/<int:nid>/edit', views.depart_edit),
# 用户管理
path('user/list', views.user_list),
]
添加views:
def user_list(request):
"""用户管理"""
us_list = models.Employee.objects.all()
return render(request, 'user_list.html', {"us_list": us_list})
编写HTML:
PS:注意在循环中的写法:
{% for obj in us_list %} <tr> <th scope="row">{{ obj.id }}</th> <td>{{ obj.name }}</td> <td>{{ obj.age }}</td> <td>{{ obj.salary }}</td> <td>{{ obj.entry_name|date:'Y-m-d' }}</td> # 时间日期 <td>{{ obj.depart.title }}</td> # 获取关联表中的字段值 <td>{{ obj.get_gender_display }}</td> # 获取字段对应的选择值 <td> <a class="btn btn-primary btn-xs" href="#">编辑</a> <a class="btn btn-danger btn-xs" href="#">删除</a> </td> </tr> {% endfor %}
{% extends 'layout.html' %}
{% block title%}
<title>用户列表</title>
{% endblock %}
{% block content %}
<div>
<div class="container">
<div style="margin-bottom: 10px">
<a class="btn btn-primary" href="#" target="_blank">
<span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
新建用户
</a>
</div>
<div class="bs-example" data-example-id="panel-without-body-with-table">
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">用户列表</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>
</tr>
</thead>
<tbody>
{% for obj in us_list %}
<tr>
<th scope="row">{{ obj.id }}</th>
<td>{{ obj.name }}</td>
<td>{{ obj.age }}</td>
<td>{{ obj.salary }}</td>
<td>{{ obj.entry_name|date:'Y-m-d' }}</td>
<td>{{ obj.depart.title }}</td>
<td>{{ obj.get_gender_display }}</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>
</div>
</div>
{% endblock %}
十、添加员工(使用ModelForm)
首先编写页面框架
添加URL
urlpatterns = [
path("admin/", admin.site.urls),
# 部门管理
path('department/list/', views.depart_list),
path('department/add/', views.depart_add),
path('department/delete/', views.depart_del),
path('department/<int:nid>/edit', views.depart_edit),
# 用户管理
path('user/list', views.user_list),
path('user/add', views.user_add),
]
添加views
需要先定义一个MyForm类,类中再定义一个Meta类,Meta类中指定了model及需要用到的字段fields = “__all__”或给一个指定的列表,如需要的字段比较多,只有少数不需要使用,可使用exclude代替fields(同样是一个列表)
from django import forms
class MyForm(forms.ModelForm):
class Meta:
model = models.Employee
fields = ['name', "pwd", "age", "salary", "entry_name", "gender", "depart"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
def user_add(request):
"""添加用户"""
form = MyForm()
return render(request, 'user_add.html', {"form": form})
编写HTML:
与前面基本一致,只是表单部分有不同:
<div class="panel-body">
<form method="post">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
</div>
完整HTML:
{% extends 'layout.html' %}
{% block title %}
<title>添加用户</title>
{% endblock %}
{% block content %}
<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 %}
{% for field in form %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
添加员工并进行验证及错误提示:
class MyForm(forms.ModelForm):
# 默认的验证只能判断空值,自定义验证项目写法如下
# name = forms.CharField(min_length=3, label="用户名")
class Meta:
model = models.Employee
fields = ['name', "pwd", "age", "salary", "entry_name", "gender", "depart"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
def user_add(request):
"""添加用户"""
if request.method == 'GET':
form = MyForm()
return render(request, 'user_add.html', {"form": form})
# 提交数据
form = MyForm(data=request.POST)
# 校验数据
if form.is_valid():
form.save()
return redirect("/user/list")
else:
return render(request, 'user_add.html', {"form": form})
表单修改:
<form method="post" no validate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label class="col-sm-2 control-label">{{ field.label }}</label>
{{ field }}
<span style="color: red;">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
十一、编辑员工
添加URL(根据员工ID):
urlpatterns = [
path("admin/", admin.site.urls),
# 部门管理
path('department/list/', views.depart_list),
path('department/add/', views.depart_add),
path('department/delete/', views.depart_del),
path('department/<int:nid>/edit', views.depart_edit),
# 用户管理
path('user/list', views.user_list),
path('user/add', views.user_add),
path('user/<int:nid>/edit', views.user_edit),
]
编写views-同样使用modelform:
def user_edit(request, nid):
"""编辑用户"""
# 根据ID获取数据
row_object = models.Employee.objects.filter(id=nid).first()
if request.method == "GET":
# 默认值设置: instance=row_object
form = MyForm(instance=row_object)
return render(request, "user_edit.html", {"form": form})
form = MyForm(data=request.POST, instance=row_object)
if form.is_valid():
form.save()
return redirect("/user/list")
return render(request, 'user_edit.html', {"form": form})
编写HTML:
{% 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 class="col-sm-2 control-label">{{ field.label }}</label>
{{ field }}
<span style="color: red;">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
十二、验证数据
方法一:
在Modelform中的fields字段中每个添加的项可以定义一个‘clean_字段名’的方法:
from django.core.exceptions import ValidationError
class MyForm(forms.ModelForm):
class Meta:
model = models.XXX
fields = ["field1", "field2"]
def clean_field1(self):
# 获取对应字段的用户输入值
field_1 = self.cleaned_data["field1"]
# 条件判断
if len(field_1) != 11:
# 验证不通过
raise ValidationError("提示信息")
# 验证通过
return field_1
方法二:
from django.core.validators import RegexValidator
class MyForm(forms.ModelForm):
# 定义字段
field1 = forms.CharField(label="xxx", validators=[RegexValidator(r'正则表达式', '错误提示信息')])