from django.core.validators import RegexValidator # 进行数据校验的正则表达式 from django.core.exceptions import ValidationError # 捕获表单提交的异常错误 from django.shortcuts import render, redirect from app.models import Department, UserInfo, PrettyNumber from django import forms # 构建表单模型 from django.utils.safestring import mark_safe # 确保传输的字符串是安全的,用于传输拼接分页的html代码 # Create your views here. def depart_list(request): """ 部门列表 """ data_list = Department.objects.all() return render(request, 'depart_list.html', {'queryset': data_list}) def depart_add(request): """ 新增部门 """ if request.method == 'GET': return render(request, 'depart_add.html') title = request.POST.get('title') Department.objects.create(title=title) return redirect('/depart/list') def depart_delete(request): """ 删除部门 """ nid = request.GET.get('nid') Department.objects.filter(id=nid).delete() return redirect('/depart/list') def depart_edit(request, nid): """ 编辑部门 nid 用于接收前端传递过来的id,他的名字要和urls.py文件中定义的一样 """ if request.method == 'GET': # 进入编辑页面 row_object = Department.objects.filter(id=nid).first() return render(request, 'depart_edit.html', {'row_object': row_object}) # 保存修改POST提交 title = request.POST.get('title') Department.objects.filter(id=nid).update(title=title) return redirect('/depart/list') def user_list(request): """ 用户列表 """ data_list = UserInfo.objects.all() return render(request, 'user_list.html', {'queryset': data_list}) def user_add(request): """ 添加用户 (原始实现方式) 缺点: 1.要重复前端form表单 2.用户提交数据未校验 3.前端输入错误没有提示 4.关联的数据要手动获取,前端要循环渲染 """ if request.method == 'GET': content = { 'gender': UserInfo.gender_choices, 'depart': Department.objects.all() } return render(request, 'user_add.html', content) name = request.POST.get('name') password = request.POST.get('password') age = request.POST.get('age') account = request.POST.get('account') create_time = request.POST.get('create_time') depart_id = request.POST.get('depart') gender = request.POST.get('gender') UserInfo.objects.create(name=name, password=password, age=age, account=account, create_time=create_time, depart_id=depart_id, gender=gender) return redirect('/user/list') class UserModelForm(forms.ModelForm): """ 用户类表单模型 作用:用于定义渲染到前端的数据,设置校验规则等 用法: 用ModelForm来操作表记录 1.基本用法:首先从django.forms导入ModelForm; 2.编写一个自己的类,继承ModelForm; 3.在新类里,设置元类Meta; 4.在Meta中,设置model属性为你要关联的ORM模型,这里是UserInfo; 5.在Meta中,设置fields属性为你要在表单中使用的字段列表; 6.列表里的值,应该是ORM模型model中的字段名。 """ # 重新定义name字段的属性和校验规则 name = forms.CharField(min_length=2, label='姓名') class Meta: model = UserInfo # 指定需要显示的表名(在models.py中定义) # 指定要操作的字段名,是一个列表 fields = ['name', 'age', 'gender', 'depart', 'create_time', 'account'] # 给表单控件逐个添加属性 # widgets = { # 'name': forms.TextInput(attrs={'class': 'form-control'}), # 'password': forms.PasswordInput(attrs={'class': 'form-control'}), # 'create_time': forms.DateInput(attrs={'class': 'form-control'}), # } # 给所有表单控件添加属性 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs = {"class": "form-control"} class PrettyNumberForm(forms.ModelForm): """ 靓号类表单模型 具体使用注解,见UserModelForm类 """ # 重新定义mobile字段的属性和校验规则 方式1 mobile = forms.CharField( min_length=11, # 最小长度 label='号码', # 通过正则进行数据校验 validators=[RegexValidator(r'^1[3-9]\d{9}$', '号码错误,长度不能超过11位')], ) class Meta: model = PrettyNumber # 指定需要显示的表名(在models.py中定义) # 指定要操作的字段名,是一个列表 # fields = ['mobile', 'price', 'level', 'status'] fields = '__all__' # 渲染所有字段 # exclude = ['level'] # 排除某个字段 # 给所有表单控件添加属性 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs = {"class": "form-control"} # 对字段进行一些数据校验或操作 方式2 # 名称必须是clean_字段名 # 也称为钩子方法,更灵活,比如手机号是否已经存在... def clean_mobile(self): txt_value = self.cleaned_data['mobile'] # 获取到用户输入的字段值 num_exist = PrettyNumber.objects.filter(mobile=txt_value).exists() if num_exist: raise ValidationError("号码已经存在") return txt_value class PrettyNumberEditForm(forms.ModelForm): """ 靓号编辑类表单模型 具体使用注解,见UserModelForm类 """ # 重新定义mobile字段的属性和校验规则 方式1 mobile = forms.CharField( label='号码11', disabled=True, ) class Meta: model = PrettyNumber # 指定需要显示的表名(在models.py中定义) # 指定要操作的字段名,是一个列表 # fields = ['mobile', 'price', 'level', 'status'] fields = '__all__' # 渲染所有字段 # 给所有表单控件添加属性 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs = {"class": "form-control"} # 对字段进行一些数据校验或操作 方式2 # 名称必须是clean_字段名 # 也称为钩子方法,更灵活,比如手机号是否已经存在... def clean_mobile(self): txt_value = self.cleaned_data['mobile'] # 获取到用户输入的字段值 # instance是编辑时传入的值,pk是id主键 nid = self.instance.id # print(self.instance.mobile) # 修改时,要排除当前号码以外的其他数据 # 也就是 where mobile=18995009009 and id!=2 num_exist = PrettyNumber.objects.filter(mobile=txt_value).exclude(id=nid) if num_exist: raise ValidationError("号码已经存在") return txt_value def user_add_modelform(request): """ 添加用户(通过Django ModelForm组件实现 最简便) """ if request.method == 'GET': form = UserModelForm() # 实例化类 return render(request, 'user_add_modelform.html', {'form': form}) # POST请求 form = UserModelForm(data=request.POST) # 拿到所有提交过来的数据 if form.is_valid(): # 数据校验 # 如果你想对数据表中的字段另外再传递值来保存,就用 # form.instance.字段名 = '值' form.instance.password = '0000' # 默认密码是0000 form.save() # 向 model = UserInfo 定义的表保存数据 return redirect('/user/list/') else: # form中带了POST过来的请求 return render(request, 'user_add_modelform.html', {'form': form}) def user_edit_modelform(request, nid): """ 用户信息修改 nid 用于接收前端传递过来的id,他的名字要和urls.py文件中定义的一样 """ # 1.先查询到该条记录 # 2.拿到POST请求过来的数据(data=request.POST),将将查询到数据对象传递给form(instance=row_data) row_data = UserInfo.objects.filter(id=nid).first() if request.method == 'GET': form = UserModelForm(instance=row_data) # 将查询到的对象传递给form return render(request, 'user_edit_modelform.html', {'form': form}) # POST请求 form = UserModelForm(data=request.POST, instance=row_data) # 拿到所有提交过来的数据 if form.is_valid(): # 数据校验 form.save() # 向 model = UserInfo 定义的表保存数据 return redirect('/user/list/') else: # form中带了POST过来的请求 return render(request, 'user_edit_modelform.html', {'form': form}) def user_delete_modelform(request, nid): """ 用户信息删除 nid 用于接收前端传递过来的id,他的名字要和urls.py文件中定义的一样 """ UserInfo.objects.filter(id=nid).delete() return redirect('/user/list/') def pn_list(request): """ 靓号列表 """ # 第一次显示的时候,查询条件也就是data_dict为空,所以查询所有数据 data_dict = {} # search_data = "" search_data = request.GET.get('searchMobile', '') # 如果提交了查询的号码,则把号码拿到后添加到字典中,同时也把该数据再返回给前端,让搜索框不丢失数据 # if request.method == 'POST': # search_data = request.POST.get('searchMobile') # data_dict['mobile__contains'] = search_data # # print(value) if search_data: data_dict['mobile__contains'] = search_data """ 分页实现,准备数据阶段 PAGE_SIZE 每页显示记录数 star_page_data 开始记录数 end_page_data 结束记录数 total_count_data 总记录数 total_count_page 总页数 """ # ########## 准备数据阶段 ########## PAGE_SIZE = 10 # 每页10条数据 page = int(request.GET.get('indexPage', 1)) # 当前页,默认第1页,如果是跳转的就读indexPage输入框内的值 star_page_data = (page - 1) * PAGE_SIZE # 开始数据 end_page_data = page * PAGE_SIZE # 结束数据 # 统计共有多少条数据 total_count_data = PrettyNumber.objects.filter(**data_dict).order_by('-level').count() # ########## 分页数据准备结束 ########## """ 生成分页导航条 计算出当前页前5页和后5页的页码 PLUS_NAV 前后显示几页 star_page 起始页 end_page 结束页 total_count_page 总页数 page_nav 导航条的html代码 """ # 计算总页数 方法:通过总记录数和每页显示数相除 # divmod函数是python自带函数,计算两数相除同时获得商和余数,例如 divmod(91,10) 结果等于 {9,1} # total_count_page总页数 , mod就是余数 total_count_page, mod = divmod(total_count_data, PAGE_SIZE) if mod: total_count_page += 1 # 如果有余数总页数+1 # 计算导航栏页码数和显示方式(要考虑翻页时的极值) # 效果是前5页和后5页 PLUS_NAV = 5 # 当数据量少比如只有100条数据以内,则展示全部导航条 if total_count_page <= PLUS_NAV * 2: star_page = 1 end_page = total_count_page else: # 大于100条数据时 显示前后5条数据 # 如果当前页小于5条(极植) if page <= PLUS_NAV: star_page = 1 end_page = PLUS_NAV * 2 else: # 当前是每后一页时(极植) if (page + PLUS_NAV) >= total_count_page: star_page = total_count_page - PLUS_NAV * 2 # 显示前10页导航 end_page = total_count_page else: star_page = page - PLUS_NAV end_page = page + PLUS_NAV # 生成分页导航条的html代码,并传递给前端 page_list = [] # 首页 # prev = '
  • 首页
  • ' prev = '
  • ' page_list.append(prev) # 上一页 if page > 1: prev = f'
  • 上一页
  • ' page_list.append(prev) for i in range(star_page, end_page + 1): # range前取后不取所以+1 if i == page: ele = f'
  • {i}
  • ' # 给当前页加效果 else: ele = f'
  • {i}
  • ' page_list.append(ele) # 下一页 if page < total_count_page: prev = f'
  • 下一页
  • ' page_list.append(prev) # 尾页 # prev = f'
  • 尾页
  • ' prev = f'
  • ' page_list.append(prev) # 构建跳转html page_nav_search = """
  • """ page_list.append(page_nav_search) page_nav = ''.join(page_list) # 因为page_nav是一个html字符串,所以在传递到前端时要转换为安全的字符串 page_nav = mark_safe(page_nav) """分页实现结束""" # 字典格式: data_dict = {‘mobile__contains’: '9999'} # **data_dict传入字典,必须以**打头 # order_by('-level') 倒序排列 # [0:10] 取前10条数据 data_list = PrettyNumber.objects.filter(**data_dict).order_by('-level')[star_page_data:end_page_data] return render(request, 'PrettyNumber_list.html', {'queryset': data_list, 'search_data': search_data, 'page_nav': page_nav}) def pn_add(request): """ 增加靓号 """ if request.method == 'GET': form = PrettyNumberForm() # 实例化表单模型类 return render(request, 'PrettyNumber_add_modelform.html', {'form': form}) # POST请求 form = PrettyNumberForm(data=request.POST) # 拿到所有提交过来的数据 if form.is_valid(): # 数据校验 # 如果你想对数据表中的字段另外再传递值来保存,就用 # form.instance.字段名 = '值' # form.instance.password = '0000' # 默认密码是0000 form.save() # 向 model = PrettyNumber 定义的表保存数据 return redirect('/PrettyNumber/list/') else: # form中带了POST过来的请求 return render(request, 'PrettyNumber_add_modelform.html', {'form': form}) def pn_edit(request, nid): """ 靓号编辑 """ row_data = PrettyNumber.objects.filter(id=nid).first() if request.method == 'GET': form = PrettyNumberEditForm(instance=row_data) # 将查询到的对象传递给form return render(request, 'PrettyNumber_edit_modelform.html', {'form': form}) # POST请求 form = PrettyNumberEditForm(data=request.POST, instance=row_data) # 拿到所有提交过来的数据 if form.is_valid(): # 数据校验 form.save() # 向 model = UserInfo 定义的表保存数据 return redirect('/PrettyNumber/list/') else: # form中带了POST过来的请求 return render(request, 'PrettyNumber_edit_modelform.html', {'form': form}) def pn_delete(request, nid): """ 靓号删除 """ PrettyNumber.objects.filter(id=nid).delete() return redirect('/PrettyNumber/list/')