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 %}