Djiango-用户管理
-
创建一些用户数据
insert into blog_employee(name,password,age,account,create_time,gender,depart_id) values("李云龙","123456",45,50000,"2020-03-24",1,102);
insert into blog_employee(name,password,age,account,create_time,gender,depart_id) values("张三丰","123456",45,60000,"2021-03-24",1,103);
insert into blog_employee(name,password,age,account,create_time,gender,depart_id) values("周杰伦","123456",45,70000,"2022-03-24",1,101);
-
用户展示 user_list.html
def users_list(req):
users_list = Employee.objects.all().order_by("id")
# for obj in users_list:
# gender 对应的数据获取
# gender_choices = (
# (1, "男"),
# (2, "女"),
# )
# gender = models.SmallIntegerField(choices=gender_choices,verbose_name="性别")
# print(obj.gender, obj.get_gender_display())
# # depart 外键值获取
# # depart = models.ForeignKey(to="Department", to_field="dep_id", on_delete=models.CASCADE, verbose_name="部门")
# print(obj.depart_id, obj.depart.title)
# # 循环取所有数据
# print(obj.id, obj.name, obj.account, obj.age, obj.create_time.strftime(
# "%Y-%m-%d"), obj.gender, obj.get_gender_display(), obj.depart_id, obj.depart.title)
# html 内写法
# <td>{{ iteam.create_time|date:"Y-m-d" }}</td>
# <td>{{ iteam.get_gender_display }}</td>
# <td>{{ iteam.depart.title }}</td>
return render(req, 'users_list.html', {"users_list": users_list})
<div class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> 用户列表
</strong>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>密码</th>
<th>年龄</th>
<th>余额/元</th>
<th>入职时间</th>
<th>性别</th>
<th>部门</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for iteam in users_list %}
<tr>
<th scope="row">{{ iteam.id }}</th>
<td>{{ iteam.name }}</td>
<td>{{ iteam.password }}</td>
<td>{{ iteam.age }}</td>
<td>{{ iteam.account }}</td>
<td>{{ iteam.create_time|date:"Y-m-d" }}</td>
<td>{{ iteam.get_gender_display }}</td>
<td>{{ iteam.depart.title }}</td>
<td>
<a class="btn btn-primary btn-xs" href="/users/{{ iteam.id }}/edit/"> 编辑 </a>
<a class="btn btn-danger btn-xs" href="/users/del/?nid={{ iteam.id }}"> 删除 </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
-
用户添加 users_add.html 原始方式
def users_add(req):
"""部门添加"""
if req.method == "GET":
# gender_choices = UserInfo.gender_choices
# depart_list = Department.objects.all()
# return render(req, "users_add.html", {"depart_list": depart_list, "gender_choices": gender_choices})
context = {
"gender_choices" : Employee.gender_choices,
"depart_list" : Department.objects.all()
}
return render(req, "users_add.html", context)
try:
# 获取提交的用户数据
users_name = req.POST.get("users_name")
users_password = req.POST.get("users_password")
users_age = req.POST.get("users_age")
users_account = req.POST.get("users_account")
users_create_time = req.POST.get("users_create_time")
users_gender = req.POST.get("users_gender")
users_depart_id = req.POST.get("users_depart_id")
# 保存到数据库
Employee.objects.create(name=users_name, password=users_password, age=users_age, account=users_account,
create_time=users_create_time, gender=users_gender, depart_id=users_depart_id)
# 重定向回用户列表
return redirect("/users/list/")
except Exception as e:
# print(e)
return render(req, "users_add.html", {"error_msg": e})
<form class="form-group" method="post" action="/users/add/">
{% csrf_token %}
<div class="form-group">
<label for="users_add"><strong>用户名:</strong></label>
<input type="text" class="form-control" name="users_name" style="width: 300px;" id="users_add" placeholder="用户名">
</div>
<div class="form-group" >
<label for="users_add"><strong>密码:</strong></label>
<input type="text" class="form-control" name="users_password" style="width: 300px;" id="users_add" placeholder="密码">
</div>
<div class="form-group" >
<label for="users_add"><strong>年龄:</strong></label>
<input type="text" class="form-control" name="users_age" style="width: 300px;" id="users_add" placeholder="年龄">
</div>
<div class="form-group" >
<label for="users_add"><strong>余额/元:</strong></label>
<input type="text" class="form-control" name="users_account" style="width: 300px;" id="users_add" placeholder="例: 10000.0">
</div>
<div class="form-group" >
<label for="users_add"><strong>入职时间:</strong></label>
<input type="text" class="form-control" name="users_create_time" style="width: 300px;" id="users_add" placeholder="例: 2023-10-10">
</div>
<div class="form-group" >
<label for="users_add"><strong>性别:</strong></label>
<!-- <input type="text" class="form-control" name="users_gender" style="width: 300px;" id="users_add" placeholder="1 或 2 ,1: 男 2: 女"> -->
<select name="users_gender" id="users_add" class="form-control" style="width: 300px;">
{% for items in gender_choices %}
<option value="{{ items.0 }}">{{ items.1 }}</option>
{% endfor %}
</select>
</div>
<div class="form-group" >
<label for="users_add"><strong>部门:</strong></label>
<!-- <input type="text" class="form-control" name="users_depart_id" style="width: 300px;" id="users_add" placeholder="例: 101"> -->
<select name="users_depart_id" id="users_add" class="form-control" style="width: 300px;">
{% for items in depart_list %}
<option value="{{ items.dep_id }}">{{ items.title }}</option>
{% endfor %}
</select>
</div>
<div class="form-group" >
<button type="submit" class="btn btn-success"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span><strong> 提 交</strong></button>
</div>
<br>
<span style="color: red;"> {{ error_msg }} </span>
</form>
-
缺点
- 数据校验较麻烦
- 数字输入错误没有错误提示
- 页面上每一个字段都需要重新写一遍
- 关联的数据,需要手动获取并循环展示在页面
-
Django组件
-
Form组件(简便)
-
初识 Form views.py
class MyForm(Form): user = forms.CharField(widget=forms.Input) pwd = forms.CharField(widget=forms.Input) email = forms.CharField(widget=forms.Input) def user_add(req): if req.method == "GET": form = MyForm() return render(req, "user_add.html", {"form": form})
- user_add_form.html
{{ form.xxx }} 可以自动生成前端代码
<form method="post"> {{ form.user }} {{ form.pwd }} {{ form.email }} </form> <!-- 或 --> <form method="post"> {% for field in form %} {{ field }} {% endfor %} </form>
-
-
ModelForm组件(最简便)
- models.py
# 员工管理系统表
class Department(models.Model):
"""部门表"""
dep_id = models.IntegerField(verbose_name="部门代码", null=True, blank=True, unique=True)
title = models.CharField(max_length=32, verbose_name='标题', null=True, blank=True, unique=True)
class Employee(models.Model):
"""员工表"""
name = models.CharField(max_length=16, verbose_name="姓名")
password = models.CharField(max_length=64, verbose_name="密码")
age = models.IntegerField(verbose_name="年龄")
account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
create_time = models.DateField(verbose_name="入职时间")
# 外键约束
# to 表示与哪张表关联
# to_field 表示表中的哪一列
# 在django中,数据表中的名称自动加上_id,也就是depart_id
# on_delete=models.CASCADE 表示级联删除(删除部门,部门下的所有员工都会被删除)
depart = models.ForeignKey(to="Department", to_field="dep_id", on_delete=models.CASCADE, verbose_name="部门")
# on_delete=models.SET_NULL, null=True, blank=True 表示置空(删除部门,部门下的所有员工的部门字段置为空)
#depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.SET_NULL, null=True, blank=True)
gender_choices = (
(1, "男"),
(2, "女"),
)
gender = models.SmallIntegerField(choices=gender_choices,verbose_name="性别")
* views.py
from django import forms
class MyForm(forms.ModelForm):
xxx = forms.CharField("...") # 自定义字段
class Meta:
field = ["name", "password", "age", "xxx"] # 按需引用models字段和自定义字段
def user_add(req):
if req.method == "GET":
form = MyForm()
return render(req, "user_add.html", {"form": form})
* user_add_modelform.html `{{ form.xxx }} 可以自动生成前端代码
`
<form method="post">
{{ form.user }}
{{ form.pwd }}
{{ form.email }}
</form>
<!-- 或 -->
<form method="post">
{% for field in form %}
{{ field }}
{% endfor %}
</form>
Django之ModelForm组件
ModelForm
a. class Meta:
model, # 对应Model的
fields=None, # 字段
exclude=None, # 排除字段
labels=None, # 提示信息
help_texts=None, # 帮助提示信息
widgets=None, # 自定义插件
error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
field_classes=None # 自定义字段类 (也可以自定义字段)
localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
如:
数据库中
2016-12-27 04:10:57
setting中的配置
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = True
则显示:
2016-12-27 12:10:57
b. 验证执行过程
is_valid -> full_clean -> 钩子 -> 整体错误
c. 字典字段验证
def clean_字段名(self):
# 可以抛出异常
# from django.core.exceptions import ValidationError
return "新值"
d. 用于验证
model_form_obj = XXOOModelForm()
model_form_obj.is_valid()
model_form_obj.errors.as_json()
model_form_obj.clean()
model_form_obj.cleaned_data
e. 用于创建
model_form_obj = XXOOModelForm(request.POST)
#### 页面显示,并提交 #####
# 默认保存多对多
obj = form.save(commit=True)
# 不做任何操作,内部定义 save_m2m(用于保存多对多)
obj = form.save(commit=False)
obj.save() # 保存单表信息
obj.save_m2m() # 保存关联多对多信息
f. 用于更新和初始化
obj = model.tb.objects.get(id=1)
model_form_obj = XXOOModelForm(request.POST,instance=obj)
...
PS: 单纯初始化
model_form_obj = XXOOModelForm(initial={...})
-
用户添加 users_add_modelform.html modelform方式优化
-
models.py
-
class Department(models.Model):
"""部门表"""
dep_id = models.IntegerField(
verbose_name="部门代码", null=True, blank=True, unique=True)
title = models.CharField(
max_length=32, verbose_name='标题', null=True, blank=True, unique=True)
def __str__(self):
# haha = str(self.dep_id) + ":" + str(self.title)
return str(self.dep_id) + ":" + str(self.title)
-
views.py
class UserModelForm(forms.ModelForm):
# xxx = forms.CharField("...") # 自定义字段
# 自定义数据校验
# 例如: 用户名最小三个字符
# name = forms.CharField(min_length=3, label="用户名")
class Meta:
model = Employee
fields = ["name", "password", "age", "account",
"create_time", "gender", "depart"] # 按需引用models字段和自定义字段
# 逐一控制标签的样式
# widgets = {
# "name": forms.TextInput(attrs={"class": "form-control"}),
# "password": forms.PasswordInput(attrs={"class": "form-control"}),
# "age": forms.TextInput(attrs={"class": "form-control"}),
# }
# 这里让日期可以手动点击鼠标选择,所以单独拎出来,加上日期插件
# widgets = {
# "create_time": forms.DateInput(attrs={'class': 'form-control', 'id': 'myDate', "style": "width: 300px;"}),
# }
widgets = {
"create_time": forms.DateTimeInput(attrs={'class': 'form-control', 'id': 'myDate', "value": "2023-01-01", "style": "width: 300px;", "placeholder": "入职日期"}),
}
# 循环找到所有的插件,添加 "class": "form-control"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
# 可以排除指定的字段
if name == "create_time":
# global widgets
# widgets = {
# "create_time": forms.DateInput(attrs={'class': 'form-control', 'id': 'myDate', "value": "2020-01-01 00:00", "style": "width: 300px;"}),
# }
continue
# print(name, field)
field.widget.attrs = {
"class": "form-control", "style": "width: 300px;", "placeholder": field.label}
def users_add_modelform(req):
"""添加用户(ModelForm版本)"""
if req.method == "GET":
form = UserModelForm()
return render(req, "users_add_modelform.html", {"form": form})
try:
# 用户POST请求提交数据,需要进行数据校验
form = UserModelForm(data=req.POST)
if form.is_valid():
print(form.cleaned_data)
# {'name': 'test', 'password': 'test', 'age': 22, 'account': Decimal('2222'), 'create_time': datetime.date(2023, 1, 5), 'gender': 1, 'depart': <Department: 101:销售>}
# 如果数据合法保存至数据库
# Employee.objects.create(...)
# 插入用户输入以外字段的值
# form.instance.字段名 = 值
form.save()
return redirect("/users/list/")
# 校验失败(在页面上显示错误信息)
return render(req, "users_add_modelform.html", {"form": form})
except Exception as e:
# print(e)
return render(req, "users_add_modelform.html", {"error_msg": e})
-
users_add_modelform.html
{% extends 'layout.html' %}
{% block css %}
{% load static %}
<link rel="stylesheet" href="{% static 'plugins/font-awesome-4.7.0/css/font-awesome.css' %}">
<link rel="stylesheet" href="{% static 'plugins/bootstrap-datetimepicker/css/bootstrap-datetimepicker.css' %}">
{% endblock %}
{% block content %}
<div class="container">
<hr>
</hr>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><strong>新建用户-ModelForm</strong></h3>
</div>
<div class="panel-body">
<form class="form-group" method="post" action="/users/add_modelform/">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label>{{ field.label }}: </label>
{{ field }}
<!-- 数据校验,显示错误信息 -->
<span style="color: red;">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<div class="form-group" >
<button type="submit" class="btn btn-success"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span><strong> 提 交</strong></button>
</div>
<br>
<span style="color: red;"> {{ error_msg }} </span>
</form>
</div>
</div>
</div>
{% endblock %}
{% block js %}
{% load static %}
<script src="{% static 'plugins/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.zh-CN.js' %}"></script>
<script>
$(function () {
$('#myDate').datetimepicker({
// format: 'yyyy-mm-dd hh:ii',
minView: "month", //选择日期后,不会再跳转去选择时分秒
format: 'yyyy-mm-dd',
startDate: '0',
language: 'zh-CN',
autoclose: true
})
})
</script>
{% endblock %}
-
注意
<!-- 关闭浏览器数据验证 -->
<form class="form-group" method="post" action="/users/add_modelform/" novalidate>
<!-- ModelForm 数据验证错误信息 -->
<span style="color: red;">{{ field.errors.0 }}</span>