Django学习记录03——员工部门案例

1、项目初始化

1.1 项目创建

在这里插入图片描述
在这里插入图片描述

1.2 APP的创建

1.2.1 方法一 命令配置

python manage.py startapp app01

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2.2 方法二 Pycharm配置

在Django Structure 中创建APP

在这里插入图片描述

2.设计表结构

2.1 表结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:
1.员工表与部门表关联时id关联  节省存储,但是查找耗时名称关联  加速查找
2.部门id的约束——用户表中的部门id只能是部门表中有的id3.部门被删除,关联对应的员工表直接删除对应员工   级联删除对应部门的员工 部门id置空''' 部门(与部门表连接)'''# 1.无约束# depart_id = models.BigIntegerField(verbose_name='部门ID')# 2.有约束#  to:与哪张表有关#  to_field: 表中哪一列关联#  会自动生成  depart_id列# depart = models.ForeignKey(to="Department",to_field="id")#  2.1部门删除# 2.1.1 级联删除# depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)# 2.1.2 置空删除# depart = models.ForeignKey(to="Department",to_field="id",null=True,blank=True,on_delete=models.SET_NULL)

2.2 部门表结构

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

2.3 员工表结构

class UserInfo(models.Model):""" 员工表 """name = models.CharField(max_length=16, verbose_name='姓名')password = models.CharField(max_length=64, verbose_name='密码')age = models.IntegerField(verbose_name='年龄')# 金额采用decimal格式,位数10位,小数点后有两位account = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='账户余额')# 入职时间采用datetime格式creat_time = models.DateTimeField(auto_now_add=True, verbose_name='入职时间')''' 部门(与部门表连接)'''depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)# 性别选择gender_choice = ((1,"男"),(2,"女"),)gender = models.SmallIntegerField(verbose_name='性别',choices=gender_choice)

2.3生成数据库

2.3.1配置mysql

安装msql包

pip install mysqlclient

setting.py

 DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'db','USER': 'root','PASSWORD': 'root','HOST': 'localhost','PORT': 3306,}}

2.3.2 创建表

makemigrations [appname]
migrate [appname]

3.案例实现

3.1 基本结构

在这里插入图片描述

3.2 实现逻辑

在这里插入图片描述

3.3 部门管理

3.3.1 部门列表的实现

depart_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.css' %}"><style>.navbar {border-radius: 0;}</style>
</head>
<body>
<nav class="navbar navbar-default"><div class="container"><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><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="#">员工管理</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">admin<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></div>
</nav>
<div class="container"><div style="margin-bottom: 10px"><a type="button" class="btn btn-success" href="/depart/add"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> 新建部门</a></div><div class="panel panel-default"><div class="panel-heading">部门列表</div><div class="bs-example" data-example-id="hoverable-table"><table class="table table-hover"><thead><tr><th>ID</th><th>部门名称</th><th>操作</th></tr></thead><tbody>{% for dept in depart_list %}<tr><th scope="row">{{ dept.id }}</th><td>{{ dept.title }}</td><td><a class="btn btn-warning btn-sm" href="/depart/{{ dept.id }}/update">编辑</a><a class="btn btn-danger btn-sm" href="/depart/del?nid={{ dept.id }}">删除</a></td></tr>{% endfor %}</tbody></table></div></div>
</div><script src="{% static 'js/jquery-3.7.1.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>

在这里插入图片描述

3.3.2 部门管理的实现逻辑

  • 显示部门数据
-- 获取数据信息,以depart_list传入前端
def depart_list(request):""" 部门列表 """'''获取数据部门信息'''depart_list = models.Department.objects.all()return render(request, "depart_list.html", {"depart_list": depart_list})
************************************************************************************** 
-- 前端展示数据
{% for dept in depart_list %}<tr><th scope="row">{{ dept.id }}</th><td>{{ dept.title }}</td><td><a class="btn btn-warning btn-sm" href="/depart/{{ dept.id }}/update">编辑</a><a class="btn btn-danger btn-sm" href="/depart/del?nid={{ dept.id }}">删除</a></td></tr>
{% endfor %}
  • 增加部门数据
-- 新建按钮跳转,新建页面
<div style="margin-bottom: 10px"><a type="button" class="btn btn-success" href="/depart/add"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> 新建部门</a>
</div>
**************************************************************************************
-- 前端页面获取添加信息,返还post请求
<div class="panel panel-default"><div class="panel-heading">部门添加</div><div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form-inline" method="post" action="/depart/add">{% csrf_token %}<div class="form-group"><label for="username">部门名称</label><input type="text" class="form-control" id="dept_title" name="title" placeholder="部门名称"></div><input type="submit" class="btn btn-success" value="提交"></form></div></div>
</div>
**************************************************************************************
-- 判断请求(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')
  • 删除部门数据
-- 前端通过删除按钮获取待删除的部门id
<a class="btn btn-danger btn-sm" href="/depart/del?nid={{ dept.id }}">删除</a>
**************************************************************************************
-- del函数post请求,接收待删除的部门id,操作数据库,重定向到部门列表页面
def depart_del(request):"""部门删除"""# http://localhost:8000/depart/del?nid=idnid = request.GET.get("nid")models.Department.objects.filter(id=nid).delete()return redirect('/depart/list')
  • 修改部门数据
-- 前端通过编辑按钮获取待修改的部门id,并发送get请求,渲染修改页面
<a class="btn btn-warning btn-sm" href="/depart/{{ dept.id }}/update">编辑</a>def depart_update(request, nid):# http://localhost:8000/depart/nid/update'''部门编辑'''if request.method == 'GET':dept = models.Department.objects.filter(id=nid).get()return render(request, "depart_update.html", {"dept": dept})<div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form-inline" method="post" action="/depart/{{ dept.id }}/update">{% csrf_token %}<div class="form-group"><label for="username">部门名称</label><input type="text" class="form-control" id="dept_title" name="title" value="{{ dept.title }}"></div><input type="submit" class="btn btn-success" value="提交"></form></div>
</div>
**************************************************************************************
-- 修改数据后,发送post请求,update函数接收请求,修改数据库
def depart_update(request, nid):# http://localhost:8000/depart/nid/update'''部门编辑'''if request.method == 'GET':dept = models.Department.objects.filter(id=nid).get()return render(request, "depart_update.html", {"dept": dept})new_title = request.POST.get("title")models.Department.objects.filter(id=nid).update(title=new_title)return redirect('/depart/list')

3.3.4 url传参的两种形式

1.get请求方法
# http://localhost:8000/depart/del?nid=id
- urls:path('depart/del', views.depart_del),
- 获取参数:<a href="/depart/del?nid={{ dept.id }}">删除</a>
- 函数:
def depart_del(request):nid = request.GET.get("nid")models.Department.objects.filter(id=nid).delete()return redirect('/depart/list')t
2.正则表达式
# http://localhost:8000/depart/nid/update
- urls:path('depart/ <int:nid> /update', views.depart_update),
- 获取参数:<a href="/depart/{{ dept.id }}/update">编辑</a>
- 函数:
def depart_update(request, nid):if request.method == 'GET':dept = models.Department.objects.filter(id=nid).get()return render(request, "depart_update.html", {"dept": dept})new_title = request.POST.get("title")models.Department.objects.filter(id=nid).update(title=new_title)return redirect('/depart/list')

3.4模板的继承

上述部门列表、部门新建、部门更新的html页面中导航栏和一些其他的部分高度相似,为避免重复,可采用模板继承

3.4.1 模板

定义母版:layout.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="{% static 'plugin...min.css' %}">{% block css %}子版css内容{% endblock %}
</head>
<body><h1>标题</h1><div>{% block content %}子版内容{% endblock %}</div><h1>底部</h1><script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>{% block js %}子版js内容{% endblock %}
</body>
</html>

3.4.2 继承模板

-- 继承母版
{% extends 'layout.html' %}--自己的css内容
{% block css %}<link rel="stylesheet" href="{% static 'pluxxx.css' %}"><style>...</style>
{% endblock %}--自己的内容
{% block content %}<h1>首页</h1>
{% endblock %}--自己的js内容
{% block js %}<script src="{% static 'js/jqxxxin.js' %}"></script>
{% endblock %}

3.4.3部门案例的模板应用

定义母版:layout.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.css' %}"><style>.navbar {border-radius: 0;}</style>{% block css %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-default"><div class="container"><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><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="#">员工管理</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">admin<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></div>
</nav>
<div class="container">{% block content %}{% endblock %}</div><script src="{% static 'js/jquery-3.7.1.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>{% block js %}{% endblock %}
</body>
</html>

dept_list.html

{% extends 'layout.html' %}{% block content %}<div style="margin-bottom: 10px"><a type="button" class="btn btn-success" href="/depart/add"><span class="glyphicon glyphicon-plus-sign"aria-hidden="true"></span> 新建部门</a></div><div class="panel panel-default"><div class="panel-heading">部门列表</div><div class="bs-example" data-example-id="hoverable-table"><table class="table table-hover"><thead><tr><th>ID</th><th>部门名称</th><th>操作</th></tr></thead><tbody>{% for dept in depart_list %}<tr><th scope="row">{{ dept.id }}</th><td>{{ dept.title }}</td><td><a class="btn btn-warning btn-sm" href="/depart/{{ dept.id }}/update">编辑</a><a class="btn btn-danger btn-sm" href="/depart/del?nid={{ dept.id }}">删除</a></td></tr>{% endfor %}</tbody></table></div></div>
{% endblock %}

dept_add.html

{% extends 'layout.html' %}{% block content %}<div class="panel panel-default"><div class="panel-heading">部门添加</div><div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form-inline" method="post" action="/depart/add">{% csrf_token %}<div class="form-group"><label for="username">部门名称</label><input type="text" class="form-control" id="dept_title" name="title" placeholder="部门名称"></div><input type="submit" class="btn btn-success" value="提交"></form></div></div></div>
{% endblock %}

dept_update.html

{% extends 'layout.html' %}{% block content %}<div class="panel panel-default"><div class="panel-heading">部门修改</div><div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form-inline" method="post" action="/depart/{{ dept.id }}/update">{% csrf_token %}<div class="form-group"><label for="username">部门名称</label><input type="text" class="form-control" id="dept_title" name="title" value="{{ dept.title }}"></div><input type="submit" class="btn btn-success" value="提交"></form></div></div></div>
{% endblock %}

3.5员工管理

3.5.1员工列表的实现

user_list.html

{% extends 'layout.html' %}{% block content %}<div style="margin-bottom: 10px"><a type="button" class="btn btn-success" href="/user/add"><span class="glyphicon glyphicon-plus-sign"aria-hidden="true"></span> 增加员工</a><atype="button" class="btn btn-success" href="/user/ModelForm/add"><span class="glyphicon glyphicon-plus-sign"aria-hidden="true"></span> 增加员工ModelForm</a></div><div class="panel panel-default"><div class="panel-heading">员工列表</div><div class="bs-example" data-example-id="hoverable-table"><table class="table table-hover"><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 user in user_list %}<tr><th scope="row">{{ user.id }}</th><td>{{ user.name }}</td><td>{{ user.password }}</td><td>{{ user.age }}</td><td>{{ user.account }}</td>
{#                        <td>{% now 'Y-m-d' %}</td>#}<td>{{ user.creat_time|date:"Y-m-d H:i:s" }}</td><td>{{  user.get_gender_display }}</td><td>{{ user.depart.title }}</td><td><a class="btn btn-warning btn-sm" href="/user/{{ user.id }}/update">编辑</a><a class="btn btn-danger btn-sm" href="/user/del?nid={{ user.id }}">删除</a></td></tr>{% endfor %}</tbody></table></div></div>
{% endblock %}

views.py

def user_list(request):'''获取用户信息'''user_list = models.UserInfo.objects.all()return render(request, "user_list.html", {"user_list": user_list})
<tbody>{% for user in user_list %}<tr><th scope="row">{{ user.id }}</th><td>{{ user.name }}</td><td>{{ user.password }}</td><td>{{ user.age }}</td><td>{{ user.account }}</td>{#<td>{% now 'Y-m-d' %}</td>#}<td>{{ user.creat_time|date:"Y-m-d H:i:s" }}</td><td>{{  user.get_gender_display }}</td><td>{{ user.depart.title }}</td></tr>{% endfor %}</tbody>

后端查询的用户列表返回user_list 为queryset类型

<QuerySet [<UserInfo: UserInfo object (1)>, <UserInfo: UserInfo object (7)>, <UserInfo: UserInfo object (8)>, <UserInfo: UserInfo object (9)>, <UserInfo: UserInfo object (10)>, <UserInfo: UserInfo object (11)>, <UserInfo: UserInfo object (12)>]>

1.当前时间的格式化输出

  • 获取当前时间:
  • python语言:datetime.datetime.now()
  • django模板语言:{% now 'Y-m-d' %}
  • 时间格式化输出
  • python语言:datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  • django模板语言:{{ {% now 'Y-m-d' %} | date:"Y-m-d" }}

2.性别的格式化输出

gender字段的定义:

gender_choice = ((1, "男"),(2, "女"),)gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choice)

user.gender:1或2``````user.get_gender_display:男或女

对于设置了choice的字段,Django会自动帮我们提供一个方法(注意是方法), 用来获取这个字段对应的要展示的值。展示带有choice属性的字段时,django会自动帮我们调用get_xxx_display(xxx为字段名,如本文的get_gender_display)方法,所以不用配置。而在我们自己写的模板中,这需要自己来写。并且为了简化模板的使用,默认只支持无参数的方法调用,你只需要写方法名称即可,后面的括号不能写,Django会自行帮你调用(如果是方法的话)。

3.关联数据的调用

depart字段的定义:

depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="id", on_delete=models.CASCADE)

表示user中会自动生成一个depart_id的字段,来关联存储depart表的内容

因此user可以直接调用depart表的字段。user.depart.xxx(depart各字段)

3.5.2 员工的删除操作

user_list.html

<td>
<a class="btn btn-danger btn-sm" href="/user/del?nid={{ user.id }}">删除</a>
</td>

采用get方式传入,待删除数据的id数据

http://localhost:8000/user/del?nid=id

views.py

def user_del(request):""" 员工删除"""nid = request.GET.get("nid")  # get获取(从url中)待删除数据的idmodels.UserInfo.objects.filter(id=nid).delete()return redirect("/user/list")

3.5.3 员工的更新操作

user_list.html

<td>
<a class="btn btn-warning btn-sm" href="/user/{{ user.id }}/update">编辑</a>
</td>

urls.py

path('user/<int:nid>/update', views.user_update)

可使用此种url进行传输待更新数据的id,与删除进行对比

http://localhost:8000/user/nid/update

user_update.html

{% extends 'layout.html' %}{% block content %}<div class="panel panel-default"><div class="panel-heading">部门修改</div><div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form" method="post" action="/user/{{ user.id }}/update">{% csrf_token %}<div class="form-group"><label>姓名</label><input type="text" class="form-control" id="dept_title" name="name" value="{{ user.name }}"></div><div class="form-group"><label>密码</label><input type="text" class="form-control" id="dept_title" name="pwd" value="{{ user.password }}"></div><div class="form-group"><label>年龄</label><input type="text" class="form-control" id="dept_title" name="age" value="{{ user.age }}"></div><div class="form-group"><label>余额</label><input type="text" class="form-control" id="dept_title" name="account"value="{{ user.account }}"></div><div class="form-group"><label>入职时间</label><input type="text" class="form-control" id="dept_title" name="creat_time"value="{{ user.creat_time|date:"Y-m-d" }}"></div><div class="form-group"><label>性别</label><select class="form-control" name="gender">{% for item in gender_list %}{% if item.1 == user.get_gender_display %}<option value="{{ item.0 }}" selected>{{ item.1 }}</option>{% else %}<option value="{{ item.0 }}">{{ item.1 }}</option>{% endif %}{% endfor %}</select></div><div class="form-group"><label>部门</label><select class="form-control" name="depart">{% for item in depart_list %}{% if item.title == user.depart.title %}<option value="{{ item.id }}" selected>{{ item.title }}</option>{% else %}<option value="{{ item.id }}">{{ item.title }}</option>{% endif %}{% endfor %}</select></div><input type="submit" class="btn btn-success" value="保存"></form></div></div></div>
{% endblock %}
<div class="form-group"><label>入职时间</label><input type="text" class="form-control" id="dept_title" name="creat_time"value="{{ user.creat_time|date:"Y-m-d" }}">
</div>
  • 入职时间自动获取当前时间并格式化
<div class="form-group"><label>性别</label><select class="form-control" name="gender">{% for item in gender_list %}{% if item.1 == user.get_gender_display %}<option value="{{ item.0 }}" selected>{{ item.1 }}</option>{% else %}<option value="{{ item.0 }}">{{ item.1 }}</option>{% endif %}{% endfor %}</select>
</div>
  • 性别下拉框遍历设置
  • 默认值设置(遍历设置)
  • choice属性采用get_gender_display调用
<div class="form-group"><label>部门</label><select class="form-control" name="depart">{% for item in depart_list %}{% if item.title == user.depart.title %}<option value="{{ item.id }}" selected>{{ item.title }}</option>{% else %}<option value="{{ item.id }}">{{ item.title }}</option>{% endif %}{% endfor %}</select>
</div>
  • 同上

views.py

def user_update(request, nid):"""员工更新"""if request.method == "GET":# context 为获取到的部门列表、性别列表、待更新用户id# 传入前端便于操作context = {"depart_list": models.Department.objects.all(),"gender_list": models.UserInfo.gender_choice,"user": models.UserInfo.objects.get(id=nid),}return render(request, "user_update.html", context)name = request.POST.get("name")password = request.POST.get("pwd")age = request.POST.get("age")account = request.POST.get("account")creat_time = request.POST.get("creat_time")gender = request.POST.get("gender")depart_id = request.POST.get("depart")# 操作数据库models.UserInfo.objects.filter(id=nid).update(name=name, password=password, age=age, account=account,creat_time=creat_time, gender=gender, depart_id=depart_id)return redirect("/user/list")

3.5.4 员工的增加操作

3.5.4.1 原始操作

类似员工的更新操作

user_list.html

<div style="margin-bottom: 10px"><a type="button" class="btn btn-success" href="/user/add"><span class="glyphicon glyphicon-plus-sign"
aria-hidden="true"></span> 增加员工</a>
</div>

user_add.html

{% extends 'layout.html' %}{% block content %}<div class="panel panel-default"><div class="panel-heading">员工添加</div><div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form" method="post" action="/user/add">{% csrf_token %}<div class="form-group"><label>姓名</label><input type="text" class="form-control" id="dept_title" name="name"></div><div class="form-group"><label>密码</label><input type="text" class="form-control" id="dept_title" name="pwd"></div><div class="form-group"><label>年龄</label><input type="text" class="form-control" id="dept_title" name="age"></div><div class="form-group"><label>余额</label><input type="text" class="form-control" id="dept_title" name="account"></div><div class="form-group"><label>入职时间</label><input type="text" class="form-control" id="dept_title" name="creat_time" value="{% now 'Y-m-d' %}"></div><div class="form-group"><label>性别</label><select class="form-control" name="gender">{% for item in gender_list %}<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><input type="submit" class="btn btn-success" value="提交"></form></div></div></div>
{% endblock %}

同更新操作

views.py

def user_add(request):'''新增员工'''if request.method == 'GET':context = {"depart_list": models.Department.objects.all(),"gender_list": models.UserInfo.gender_choice,}return render(request, "user_add.html", context)# 缺少数据校验和错误提示# 前端的每一个字段都得写一遍# 关联的数据,需要手动获取并循环展示name = request.POST.get("name")password = request.POST.get("pwd")age = request.POST.get("age")account = request.POST.get("account")creat_time = request.POST.get("creat_time")gender = request.POST.get("gender")depart_id = request.POST.get("depart")models.UserInfo.objects.create(name=name, password=password, age=age, account=account, creat_time=creat_time,gender=gender, depart_id=depart_id)return redirect('/user/list')

原始方法的弊端

  • 缺少数据校验和错误提示
  • 前端的每一个字段都得写一遍
  • 关联的数据(depart)需要手动获取并且循环展示
3.5.4.2 form组件

views.py

class MyForm(Form):<-----------------------------------------user = forms.CharField(widget=forms.Input)				|pwd = form.CharFiled(widget=forms.Input)				|email = form.CharFiled(widget=forms.Input)				|account = form.CharFiled(widget=forms.Input)			|create_time = form.CharFiled(widget=forms.Input)		|depart = form.CharFiled(widget=forms.Input)				|gender = form.CharFiled(widget=forms.Input)				||
## 封装form, form = MyForm()运行自动生成input输入框			||
def user_add(request):										|if request.method == "GET":								|form = MyForm()>-------------------------------------##  form 此时为一系列输入框return render(request, 'user_add.html',{"form":form})

user_add.html

<form method="post">{% for field in form%}{{ field }}{% endfor %}<!-- <input type="text"  placeholder="姓名" name="user" /> -->
</form>
<form method="post">{{ form.user }}{{ form.pwd }}{{ form.email }}<!-- <input type="text"  placeholder="姓名" name="user" /> -->
</form>
3.5.4.3 ModelsForm组件

views.py

class user_ModelForm(forms.ModelForm):password = forms.CharField(min_length=6, label="密码")class Meta:# 自动获取UserInfo创建的各字段model = models.UserInfo# fields存储UserInfo创建的各字段的input输入框fields = ['name', 'password', 'age', 'account', 'creat_time', 'gender', 'depart']def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 循环找到所有的插件,添加了class="form-control"print(self.fields) #####---------------1for key, value in self.fields.items():print(value.widget)if key == "creat_time":# python中当前时间并且格式化形式datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")# django模板语言当前时间并且格式形式 {% now 'Y-m-d' %}  或  {{ user.creat_time|date:"Y-m-d" }}value.widget.attrs = {"class": "form-control", "placeholder": value.label,"value": datetime.datetime.now().strftime("%Y-%m-%d")}else:value.widget.attrs = {"class": "form-control", "placeholder": value.label}def user_ModelForm_add(request):if request.method == 'GET':# form为userinfo各字段的表单form = user_ModelForm()print(form)return render(request, "user_ModelForm_add.html", {"form": form})# 将前端表单的post请求,直接传入form对象中form = user_ModelForm(request.POST)# 判断数据是否合法有效(校验规则————models中建表表项规则 + class user_ModelForm(forms.ModelForm)重新定义表项规则)if form.is_valid():# 将表单保存到数据库中form.save()return redirect('/user/list')# 校验失败(在页面显示错误信息) form.error()含有错误return render(request, "user_ModelForm_add.html", {"form": form})

输入框加入样式的方法

  • widgets方法
class user_ModelForm(forms.ModelForm):password = forms.CharField(min_length=6, label="密码")class Meta:# 自动获取UserInfo创建的各字段model = models.UserInfo# fields存储UserInfo创建的各字段的input输入框fields = ['name', 'password', 'age', 'account', 'creat_time', 'gender', 'depart']# 给输入框上样式的方法widgets = {"name": forms.TextInput(attrs={"class": 'form-control'}),"password": forms.TextInput(attrs={"class": 'form-control'}),"age": forms.NumberInput(attrs={"class": 'form-control'}),"account": forms.NumberInput(attrs={"class": 'form-control'}),"creat_time": forms.DateTimeInput(attrs={"class": 'form-control'}),"gender": forms.Select(attrs={"class": 'form-control'}),"depart": forms.Select(attrs={"class": 'form-control'}),}
  • 自定义方法
class user_ModelForm(forms.ModelForm):password = forms.CharField(min_length=6, label="密码")class Meta:# 自动获取UserInfo创建的各字段model = models.UserInfo# fields存储UserInfo创建的各字段的input输入框fields = ['name', 'password', 'age', 'account', 'creat_time', 'gender', 'depart']def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 循环找到所有的插件,添加了class="form-control"print(self.fields)for key, value in self.fields.items():print(value.widget)if key == "creat_time":value.widget.attrs = {"class": "form-control", "placeholder": value.label,"value": datetime.datetime.now().strftime("%Y-%m-%d")}else:value.widget.attrs = {"class": "form-control", "placeholder": value.label}

要点1

# 自动获取UserInfo创建的各字段
model = models.UserInfo
# fields存储UserInfo创建的各字段的input输入框
fields = ['name', 'password', 'age', 'account', 'creat_time', 'gender', 'depart']

要点2

①处field返回值为字典,key为表的各字段. value为form对象,存储form中每一个输入框格式

{'name': <django.forms.fields.CharField object at 0x000001CFBED9A1D0>, 'password': <django.forms.fields.CharField object at 0x000001CFBED9A410>,'age': <django.forms.fields.IntegerField object at 0x000001CFBED9A5D0>, 'account': <django.forms.fields.DecimalField object at 0x000001CFBED9A850>, 'creat_time': <django.forms.fields.DateTimeField object at 0x000001CFBED9AAD0>,'gender': <django.forms.fields.TypedChoiceField object at 0x000001CFBED9AD50>, 'depart': <django.forms.models.ModelChoiceField object at 0x000001CFBED9B250>
}

②处self.fields.items()遍历字典的每一个键值对

key为表的各字段;value为forms对象,存储form为各字段的格式;value.widget 操作每一项的输入框

字段name为例
value:       <django.forms.fields.CharField object at 0x000001CFBED9A1D0>
value.widget:<django.forms.widgets.TextInput object at 0x000001DDA8476C50>

value.widget.attrs给输入框增加样式

value.widget.attrs = {"class": "form-control", "placeholder": value.label,xxx:xxx}

特别注意:使用此方法,只要使用class Department,立马输出对应内容

**此处关联数据无需遍历,只需在构建关联表时,定义默认输出值即可

class Department(models.Model):""" 部门表 """title = models.CharField(max_length=32, verbose_name='部门')# 默认返回部门名称def __str__(self):return self.title

在这里插入图片描述

若不采用,默认返回的时department的表对象,若要取得title字段,还得特殊处理

在这里插入图片描述

操作函数

def user_ModelForm_add(request):if request.method == 'GET':# form为userinfo各字段的表单form = user_ModelForm()print(form)return render(request, "user_ModelForm_add.html", {"form": form})# 将前端表单的post请求,直接传入form对象中form = user_ModelForm(request.POST)# 判断数据是否合法有效(校验规则————models中建表表项规则 + class user_ModelForm(forms.ModelForm)重新定义表项规则)if form.is_valid():# 将表单保存到数据库中form.save()return redirect('/user/list')# 校验失败(在页面显示错误信息) form.error()含有错误return render(request, "user_ModelForm_add.html", {"form": form})

要点1

form = user_ModelForm() 返回一个生成好的表

<div><label for="id_name">姓名:</label><input type="text" name="name" class="form-control" placeholder="姓名" required id="id_name">   </div>
<div><label for="id_password">密码:</label><input type="text" name="password" class="form-control" placeholder="密码" required id="id_password"></div><div><label for="id_age">年龄:</label><input type="number" name="age" class="form-control" placeholder="年龄" required id="id_age"></div><div><label for="id_account">账户余额:</label><input type="number" name="account" class="form-control" placeholder="账户余额" required id="id_account"></div><div><label for="id_creat_time">入职时间:</label><input type="text" name="creat_time" class="form-control" placeholder="入职时间" value="2024-02-21" required id="id_creat_time"></div><div><label for="id_gender">性别:</label><select name="gender" class="form-control" placeholder="性别" required id="id_gender"><option value="" selected>---------</option><option value="1"></option><option value="2"></option></select></div><div><label for="id_depart">部门:</label><select name="depart" class="form-control" placeholder="部门" required id="id_depart"><option value="" selected>---------</option><option value="1">销售部</option><option value="2">it宣传部</option><option value="3">计算机科学部</option></select></div>

要点2

前端的应用

{% extends 'layout.html' %}{% block content %}<div class="panel panel-default"><div class="panel-heading">员工添加</div><div class="panel-body"><div class="bs-example" data-example-id="simple-form-inline"><form class="form" method="post" action="/user/ModelForm/add" novalidate>{% csrf_token %}{#创建表单,form为userinfo各字段的表单#}{#每一个field都是一个字段的输入框#}{% for field in form %}<div class="form-group"><label>{{ field.label }}</label>{{ field }}</div>{% endfor %}<input type="submit" class="btn btn-success" value="提交"></form></div></div></div>
{% endblock %}

要点3:校验和错误提示

    # 将前端表单的post请求,直接传入form对象中,此时的form中含有form结构以及输入的数据form = user_ModelForm(request.POST)if form.is_valid():# 将表单保存到数据库中form.save()return redirect('/user/list')# 校验失败(在页面显示错误信息) form.error()含有错误return render(request, "user_ModelForm_add.html", {"form": form})
  • 判断数据是否合法有效
    1.校验规则————models中建表表项规则

    class UserInfo(models.Model):""" 员工表 """name = models.CharField(max_length=16, verbose_name='姓名')password = models.CharField(max_length=64, verbose_name='密码')age = models.IntegerField(verbose_name='年龄')# 金额采用decimal格式,位数10位,小数点后有两位account = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='账户余额')# 入职时间采用datetime格式creat_time = models.DateTimeField(verbose_name='入职时间')depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="id", on_delete=models.CASCADE)# 性别选择gender_choice = ((1, "男"),(2, "女"),)gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choice)
    

    2.class user_ModelForm(forms.ModelForm)重新定义表项规则

    在这里插入图片描述

  • 保存到数据库

form.save()直接将表单字段以及对应的数据,存入数据库的对应字段

  • 错误提示

此时的form中不仅存放着form结构以及输入的数据还有一系列form有效信息、错误提示等form对象含有的信息

form.error存放错误信息 field.errors.0存放错误提示的第一条信息

{% for field in form %}<div class="form-group"><label>{{ field.label }}</label>{{ field }}<span style="color: red">{{ field.errors.0 }}</span></div>
{% endfor %}

在这里插入图片描述

	name = models.CharField(max_length=16, verbose_name='姓名')password = models.CharField(max_length=64, verbose_name='密码')age = models.IntegerField(verbose_name='年龄')# 金额采用decimal格式,位数10位,小数点后有两位account = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='账户余额')# 入职时间采用datetime格式creat_time = models.DateTimeField(verbose_name='入职时间')depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="id", on_delete=models.CASCADE)# 性别选择gender_choice = ((1, "男"),(2, "女"),)gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choice)

2.class user_ModelForm(forms.ModelForm)重新定义表项规则

[外链图片转存中…(img-LcCgOz9Y-1708496635162)]

  • 保存到数据库

form.save()直接将表单字段以及对应的数据,存入数据库的对应字段

  • 错误提示

此时的form中不仅存放着form结构以及输入的数据还有一系列form有效信息、错误提示等form对象含有的信息

form.error存放错误信息 field.errors.0存放错误提示的第一条信息

{% for field in form %}<div class="form-group"><label>{{ field.label }}</label>{{ field }}<span style="color: red">{{ field.errors.0 }}</span></div>
{% endfor %}

[外链图片转存中...(img-I43rGkJh-1708496635163)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/693600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024信息工程、软件与计算机工程国际会议(ICIESCE2024)

2024信息工程、软件与计算机工程国际会议&#xff08;ICIESCE2024) 会议简介 随着互联网的不断创新&#xff0c;信息工程、软件和计算机工程在各个领域得到了广泛应用。为了为来自世界各地的专家学者提供一个分享通信和计算机工程领域研究成果的平台&#xff0c;2024年信息工…

Leetcode刷题笔记题解(C++):203. 移除链表元素

思路&#xff1a;不同的情况出现了&#xff0c;就是第一个节点要是为等于val的节点&#xff0c;可以新建一个节点&#xff0c;并next指向head&#xff0c;这样就可以遍历新的链表来删除节点 /*** Definition for singly-linked list.* struct ListNode {* int val;* L…

Java最全面试总结——5. MyBatis篇

1、什么是MyBatis &#xff08;1&#xff09;Mybatis是一个半ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它内部封装了JDBC&#xff0c;开发时只需要关注SQL 语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直…

深度解析Sora的核心技术

Sora要解决的核心问题 Sora面临的挑战是将不同类型的视觉信息&#xff0c;如视频、文本、图像和声音等&#xff0c;整合为一种共同的表征形式。这种转换是实现统一训练过程的关键&#xff0c;旨在将各类数据集中到一个训练框架中&#xff0c;以便于进行大规模的统一学习。简而…

rime 输入²⁰²⁴/₀₂.₂₁ 格式日期

如何书写一个日期,例如 2024/02/21 星期三、Feb. 21th, 2024、20240221、甲辰(龙)年正月十二,现在我们介绍一种新的日期格式 ⁰⁴/₀₂.₂₁ 的输入方法。 上标字符 在rime输入法中,我们可以使用符号/来启动特殊符号的输入,例如我们可以通过/sb来输入上标字符,如下👇:…

WebRTC最新版报错解决:city.wav:missing and no known rule to make it (二十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

CheatEngine基础进阶篇

我们在上一篇文章里说了CE的安装,汉化以及最基础最基础的值扫描和修改方法,当然很多游戏不能通过这些简单的手段就能达到修改值的效果,因此我们还需要掌握以下几个重要的知识点: 指针寻址 上一步阐述了如何使用"代码查找"功能对付变化位置的数据地址,但这种方法…

鸿蒙应用开发,比 React 体验更好

痛点 一直以来&#xff0c;使用 HTML CSS 来表达 UI 结构&#xff0c;都有一个若隐若现的痛点。痛点来源主要体现在 DOM 结构的语义表现力不足。 例如这样一段代码&#xff0c;我们能够很清晰的知道 DOM 结构是怎么样的&#xff0c;但是其具体的布局结构方式和特性就不知道了…

Redis面试题关于持久化的问题

什么是Redis持久化&#xff1f;Redis有哪几种持久化方式&#xff1f;优缺点是什么&#xff1f; 持久化就是把内存的数据写到磁盘中去&#xff0c;防止服务宕机了内存数据丢失。 Redis 提供了两种持久化方式:RDB&#xff08;默认&#xff09; 和AOF RDB&#xff1a; rdb是Red…

五种多目标优化算法(MOJS、MOGWO、NSWOA、MOPSO、NSGA2)性能对比,包含6种评价指标,9个测试函数(提供MATLAB代码)

一、5种多目标优化算法简介 1.1MOJS 1.2MOGWO 1.3NSWOA 1.4MOPSO 1.5NSGA2 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数&#xff08;zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3&#xff09;&#xff0…

域名 SSL 证书信息解析 API 数据接口

域名 SSL 证书信息解析 API 数据接口 网络工具&#xff0c;提供域名 SSL 证书信息解析&#xff0c;多信息查询&#xff0c;毫秒级响应。 1. 产品功能 提供域名 SSL 证书信息解析&#xff1b;最完整 SSL 属性信息解析&#xff1b;支持多种元素信息抽取&#xff0c;包括主题的可…

Sample Pairing(ICLR 2018)

paper&#xff1a;Data Augmentation by Pairing Samples for Images Classification 本文的创新点 本文提出了一种新的应用于图像分类的数据增强方法SamplePairing&#xff0c;这种简单的数据增强技术显著提高了所有测试的数据集的分类精度。此外当训练集中的样本数量非常少…

Web前端3D JS框架和库 整理

在WebGL库和SVG/Canvas元素的支持下&#xff0c;JavaScript变得惊人的强大。几乎可以为网络构建任何东西&#xff0c;包括基于浏览器的游戏和本地应用&#xff0c;许多最新的突破性功能都在3D上运行。 为此&#xff0c;「数维图小编」整理了19个交互式3D Javascript库和框架&am…

NestJS入门6:日志中间件

前文参考&#xff1a; NestJS入门1 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 NestJS入门4&#xff1a;MySQL typeorm 增删改查 NestJS入门5&#xff1a;加入Swagger 1. 安装 nest g middleware logger middleware​ ​ ​ 2. lo…

关于发送邮件时Reply Reply All和Forward的区别

我们发送邮件的时候总是会纠结到底是用回复&#xff0c;还是回复全部&#xff0c;还是转发。 回复- 仅回复发件人。 全部回复- 回复发件人和抄送/密件抄送的联系人。 转发- 将电子邮件的副本发送给其他收件人。 这几种情形分别在什么时候用呢&#xff1f; 回复 比如Alen给你…

阿里云带宽

&#x1f4d1;前言 本文主要是如何将阿里云服务器迁移实现数据转移的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️** &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日…

两年外包生涯做完,感觉自己废了一半....

先说一下自己的情况。大专生&#xff0c;17年通过校招进入湖南某软件公司&#xff0c;干了接近2年的点点点&#xff0c;今年年上旬&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在一个企业干了五年的功能测试…

golang入门介绍-1

今天开始发布关于go语言入门到实战内容&#xff0c;各位小伙伴准备好。 go介绍 Go语言&#xff08;或 Golang&#xff09;起源于 2007 年&#xff0c;并在 2009 年正式对外发布。是由 Google 公司开发的一种静态强类型、编译型、并发型、并具有垃圾回收功能的编程语言。 Go 是…

YOLOv5 + Flask + Vue实现基于深度学习算法的垃圾检测系统源码+数据库

✨界面展示 登录 注册 垃圾检测 用户管理 404 Not Found页面 403 拒绝访问页面 黑暗模式 深蓝模式 灰色模式 色弱模式 ✨技术特性 深度学习 YOLOv5&#x1f680;&#xff1a;高效、准确的目标检测算法&#xff0c;实时识别检测图像和视频中的各种对象PyTorch&#xff1a;机器…

【centos】【vsftpd】本地用户登录配置

目录 安装vsftpd和ftp本地用户登录-不限制访问目录本地用户登录-限制访问目录有可能影响连接的问题pam认证selinux策略被动模式防火墙ipv4和ipv6 报错1、 530 Login incorrect2、500 OOPS: vsftpd: refusing to run with writable root inside chroot()3、227 Entering Passive…