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年信息工…

Linux(四)__用户和用户组管理

介绍 Linux系统是一个多用户多任务的分时操作系统。 Linux 系统支持多个用户在同一时间内登陆&#xff0c;不同用户可以执行不同的任务&#xff0c;并且互不影响。不同用户具有不问的权限&#xff0c;毎个用户在权限允许的范围内完成不间的任务&#xff0c;Linux 正是通过这种…

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

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

MSSQL运用

做过的事情&#xff0c;隔几年又再做相同的事情&#xff0c;做一下记录。 角色与权限 创建账号与设定执行存储过程权限 Use testDB CREATE LOGIN acct WITH PASSWORDp1 CREATE USER acct FOR LOGIN acct GO GRANT EXECUTE ON SP_Test TO acct; GO 存储过程 调用写好的SQL语…

【水文】qsort排序

#include <stdio.h> #include <stdlib.h> // 比较函数&#xff0c;用于qsort排序 int compare(const void *a, const void *b) { return *(int *)a - *(int *)b; } int main() { int arr[] {9, 5, 7, 3, 1}; int size sizeof(arr) / sizeof(int); printf(&quo…

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

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

四个ChatGPT在学术论文写作中的要点!【建议收藏】

在论文写作过程中&#xff0c;写作不仅是一种表达&#xff0c;更是一种艺术。论文写作是一项复杂而精细的任务&#xff0c;它要求作者不仅能清晰地传达思想&#xff0c;还要能够精确地界定研究范围和问题。这是一个充满挑战的过程&#xff0c;特别是当你试图将那些盘旋在脑海中…

深度解析Sora的核心技术

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

http 和 https 的区别?

目录 1.http 和 https 的基本概念 2.http 和 https 的区别 3.https 协议的工作原理 4.https 协议的优点 5.https 协议的缺点 1.http 和 https 的基本概念 http: 超文本传输协议&#xff0c;是互联网上应用最为广泛的一种网络协议&#xff0c;是一个客户端和服务器端请求和…

穿越时空的命令行:TELNET的历史、原理与未来展望

引言 TELNET&#xff0c;代表"远程终端协议"&#xff0c;是一种允许用户通过互联网或局域网在本地计算机上登录并操作远程计算机的协议。它提供了一种简单的方式来访问远程服务器&#xff0c;执行命令并管理资源&#xff0c;是早期互联网重要的通信协议之一。 TELN…

lodash库中的函数处理嵌套的对象和数组的函数

import { isArray, camelCase, isObject, snakeCase, transform } from lodash-es;const toSnakeCase obj > transform(obj, (acc, value, key, target) > {const camelKey isArray(target) ? key : snakeCase(key);acc[camelKey] isObject(value) ? toSnakeCase(va…

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;但是其具体的布局结构方式和特性就不知道了…

vue.config.js中proxy配置

这里以axios发请求为例 axios.get("/abc/def"); axios.get("/abc/ghi"); axios.post("/abc/jkm"); //axios发送的请求是本地的服务器地址拼接上发送的请求&#xff0c;如 http://localhost:8080/abc/def如果发送的请求都以 /abc 开头&#xff0…

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

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

考什么呢?

年后的第一天复工&#xff1a; 请了一天假&#xff0c;迟回来一天&#xff0c;等到中午吃饭的时候&#xff0c;有些恍惚&#xff0c;感觉身边的人自从上班之后&#xff0c;每天过的麻木的生活&#xff0c;到饭点了&#xff0c;就去吃饭&#xff0c;生活没有一丝激情&#xff0c…

C语言获取时间函数大全

一、最简单获取秒数的&#xff0c;windows和linux逗支持用time()函数,获取从1970年到现在过了多少秒&#xff0c;time_t其实是long int 类型 time_t starttime(NULL); for(long i0;i<10000000000;) i1; time_t endtime(NULL) printf("经过了%d秒",end-start); 二…

五种多目标优化算法(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…