如果你有仔细看《第9天 | Django3.0项目实战,部门管理系统的表单》中的forms.py文件的话,你就会知道,DepartmentForm类中的类型属性,和models的是一模一样的。
既然是一样,那是否可以进行合并呢?--答案肯定是Yes啦。
10.1 模型表单
在forms.py中,定义一个DepartmentModelForm类,继承forms.ModelForm,在其内部类Meta中进行一番折腾。
from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
import re
from .models import Department
class DepartmentModelForm(forms.ModelForm):
class Meta:
model = Department
# 不显示exclude中指定的字段
exclude = ['createDate']
# 定义标签
labels = {
'name': '部门名称',
'leader': '负 责 人:',
'phone': '手 机 号:',
'region': '所在区域:',
'address': '办公位置:',
'longitude': '区域经度:',
'latitude': '区域纬度:',
}
choice = (("集团总部", "集团总部"), ("华南区域", "华南区域"),
("华北区域", "华北区域"), ("华东区域", "华东区域"),)
# 定义html控件
widgets = {
'name': widgets.TextInput(attrs={"placeholder":
"请输入部门名称", "class": "form-control"}),
'leader': widgets.TextInput(attrs={"placeholder":
"请输入负责人", "class": "form-control"}),
'phone': widgets.NumberInput(attrs={"placeholder":
"请输入手机号", "class": "form-control"}),
'region': widgets.Select(choices=choice, attrs={"class":
"form-control"}),
'address': widgets.TextInput(attrs={"placeholder":
"办公所在位置", "class": "form-control"}),
'longitude': widgets.NumberInput(attrs={"placeholder":
"区域所在经度", "class": "form-control"}),
'latitude': widgets.NumberInput(attrs={"placeholder":
"区域所在纬度", "class": "form-control"}),
}
# 定义错误提示信息
error_messages = {
"name": {
'required': '部门名称不能为空,请输入!',
'max_length': "部门名称太长了!"},
'leader': {
'required': '负责人不能为空,请输入!',
'max_length': '负责人名字太长了!'},
'phone': {
'required': '手机号不能为空,请输入!'},
}
# 手机号验证
def clean_phone(self):
phone = str(self.cleaned_data.get('phone'))
mobile_re = re.compile(r'^(13[0-9]|15[012356789]
|17[678]|18[0-9]|14[57])[0-9]{8}#39;)
if not mobile_re.match(phone):
raise ValidationError('请输入正确的手机号!')
return phone
DepartmentModelForm中Meta的内容定义是不是感觉似曾相识?没错,基本上可以直接从DepartmentForm拷贝过来,只是Meta更具条理性,更具可读性,它的属性选项,除了几个特有的,其他的跟Form中的含义是一样的。注意一点:自定义规则函数,不在Meta内部,而是在跟它平级的地方。Meta的属性选项一览表。
10.2 业务逻辑
在views.py中改造create函数的同时,把其他功能(修改、详细信息、列表、模糊查询)也一并给实现了。其实一切并没那么复杂,就算是分页。
仔细阅读Views.py代码之后,不知你有没有发现:有一个与众不同,异于他人的人物--DepartmentList出现。如果有,那么恭喜你,你真的太适合当程序猿了;如果没有,那么也恭喜你,你终于有时间起身运动,醒醒目了。
from django.shortcuts import render, redirect, get_object_or_404
from department.forms import DepartmentModelForm
from department.models import Department
from django.views.generic import ListView
# 判断部门名称是否已存在
def name_exist(name):
is_exist = Department.objects.filter(name=name).exists()
if is_exist:
return True
else:
return False
# 添加数据
def create(request):
form = DepartmentModelForm()
if request.method == 'POST':
msg = ''
form = DepartmentModelForm(request.POST)
if form.is_valid():
name = form.cleaned_data.get('name')
if name_exist(name):
form.add_error('name', "部门名称已存在,请确认!")
msg = ''
else:
form.save()
msg = '恭喜你,创建部门信息成功!'
form = DepartmentModelForm() # 重置表单内容--清空
return render(request, 'department/create.html',
{'form': form, 'msg': msg})
else:
return render(request, 'department/create.html', {'form': form})
# 修改数据
def update(request, depart_id):
department = get_object_or_404(Department, pk=depart_id)
if request.method == 'POST':
msg = ''
form = DepartmentModelForm(request.POST)
if form.is_valid():
name = form.cleaned_data.get('name')
# 如果部门名称进行了修改,需要判断是否重名
if name != department.name and name_exist(name):
form.add_error('name', "部门名称已存在,请确认!")
msg = ''
else:
form.save()
msg = '恭喜你,修改部门信息成功!'
return render(request, 'department/update.html',
{'form': form, "depart_id": depart_id,
'msg': msg})
else:
form = DepartmentModelForm(instance=department)
return render(request, 'department/update.html',
{'form': form, "depart_id": depart_id})
class DepartmentList(ListView):
model = Department
template_name = 'department/index.html'
paginate_by = 5
def get_queryset(self, *args, **kwargs):
name = self.request.GET.get('name', '')
if name != '':
return Department.objects.filter(name=name)
.order_by('-createDate')
else:
return Department.objects.all().order_by('-createDate')
def get_context_data(self, **kwargs):
name = self.request.GET.get('name', '')
context = super().get_context_data(**kwargs)
context['name'] = name
return context
# 删除数据
def delete(request, depart_id):
department = get_object_or_404(Department, pk=depart_id)
department.delete()
return redirect('/department/')
# 详细信息
def detail(request, depart_id):
department = get_object_or_404(Department, pk=depart_id)
return render(request, 'department/detail.html',
{'department': department})
为了方便咱们实现视图和表单相关的功能,Django框架真可谓煞费苦心,特意准备了ListView、CreateView、UpdateView、DeleteView、DetailView等封装类。有类实现方式,有函数实现方式,怎么实现方便就怎么来,你喜欢就好。
10.3 urls配置
有关urls.py的完整内容秀出来一下,方便你使用。注意其中对类(DepartmentList)的配置方式,它的结尾是用as_view()的,别搞错了。
from django.urls import path
from . import views
app_name = 'department'
urlpatterns = [
path('', views.DepartmentList.as_view(), name='index'),
path('create/', views.create, name='create'),
path('delete/<int:depart_id>/', views.delete, name='delete'),
path('update/<int:depart_id>/', views.update, name='update'),
path('detail/<int:depart_id>/', views.detail, name='detail'),
]
在浏览器输入http://127.0.0.1:8000/department/create/的访问结果。
好了,有关部门管理系统的表单升级的内容,老陈讲完了,如果觉得对你有所帮助,希望你能转发点赞,让更多的人看到这篇文章。你的转发和点赞,就是对老陈继续创作和分享最大的鼓励。
一个当了10年技术总监的老家伙,分享多年的编程经验。想学编程的朋友,可关注今日头条:老陈说编程。我在分享Python,前端、Java和App方面的干货。关注我,没错的。