流程都是一样的。就不在详细的记录。只写一点需要注意的地方! 或者 可以改进的地方!
1. 用户表中 只有。 name password email 三个字段。 但是添加用户的页面,应该还要有确认密码的字段。
所以,在UserInfoModelForm(forms.ModelForm): 中需要自己添加一个字段:
confirm_password = forms.CharField(label="确认密码")
2. 样式问题,因为是基于bootstrap 所以会简单很多。 添加class属性的方法, 有两种:
a. 手动添加:
class Meta: model = models.UserInfo fields = ["name", "password", "confirm_password", "email"] 手动的修改,显示什么样的错误信息 # 这里我是修改settings中的,语言配置。 改成 zh-hans error_messages = { "name": {"required": "用户名不能为空"}, "password": {"required": "密码不能为空"}, "confirm_password": {"required": "确认密码不能为空"}, "email": {"required": "邮箱不能为空"}, }
widgets = {"title": forms.TextInput(attrs={"class": "form-control"})}
通过widgets 属性, 对每一个字段,添加属性。 比较麻烦。
b. 使用初始化方法, 继承父类。进行修改。
def __init__(self, *args, **kwargs): super(UserInfoModelForm, self).__init__(*args, **kwargs) # 循环父类中生成的所有的字段,为每一个字段添加样式, 一次性为所有字典添加样式 for name, field in self.fields.items(): field.widget.attrs["class"] = "form-control"
3. 然后是,局部钩子。 错误信息的展示:
def clean_confirm_password(self): ''' 检测两次密码 是否一致 :return: ''' password = self.cleaned_data.get("password") confrim_password = self.cleaned_data.get("confirm_password") if password != confrim_password: raise ValidationError("两次密码输入不一致") return confrim_password
4. 编辑页面 与 重置密码。
对于用户的编辑,普通信息和 密码, 应该要分开进行。处理。 所以新添加两个 forms 组件。
全部的forms组件:
from django import forms from django.core.exceptions import ValidationError, NON_FIELD_ERRORS from rbac import models import re class UserInfoModelForm(forms.ModelForm): ''' 用户 添加, form组件 ''' confirm_password = forms.CharField(label="确认密码") class Meta: model = models.UserInfo fields = ["name", "password", "confirm_password", "email"] widgets = { "name":{} } def __init__(self, *args, **kwargs): super(UserInfoModelForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs["class"] = "form-control" def clean_confirm_password(self): ''' 检测两次密码 是否一致 :return: ''' password = self.cleaned_data.get("password") confrim_password = self.cleaned_data.get("confirm_password") if password != confrim_password: raise ValidationError("两次密码输入不一致") return confrim_password class UpdateUserInfoModelForm(forms.ModelForm): ''' 修改用户时, 使用这个form组件 ''' class Meta: model = models.UserInfo fields = ["name", "email"] def __init__(self, *args, **kwargs): super(UpdateUserInfoModelForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs["class"] = "form-control" class ResetPasswordUserInfoModelForm(forms.ModelForm): '''重置密码的工作''' confirm_password = forms.CharField(label="确认密码") class Meta: model = models.UserInfo fields = ["password", "confirm_password"] def __init__(self, *args, **kwargs): super(ResetPasswordUserInfoModelForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs["class"] = "form-control" def clean_confirm_password(self): ''' 检测两次密码 是否一致 :return: ''' password = self.cleaned_data.get("password") confrim_password = self.cleaned_data.get("confirm_password") if password != confrim_password: raise ValidationError("两次密码输入不一致") return confrim_password
视图函数部分:
'''角色管理''' from django.shortcuts import HttpResponse, render, redirect from django.http import JsonResponse from django.urls import reverse from rbac import models from rbac.forms.user import UserInfoModelForm,UpdateUserInfoModelForm,ResetPasswordUserInfoModelForm def user_list(request): ''' 角色列表的功能 :param request: :return: ''' user_queryset = models.UserInfo.objects.all() return render(request, "rbac/user_list.html", locals()) def user_add(request): ''' 添加角色的功能 :param request: :return: ''' forms = UserInfoModelForm() if request.method == "POST": forms = UserInfoModelForm(request.POST) if forms.is_valid(): # 验证成功 forms.save() # 进行保存 return redirect(reverse("rbac:user_list")) else: return render(request, "rbac/change.html", {"forms": forms}) return render(request, "rbac/change.html", {"forms": forms}) def user_edit(request, pk): ''' 编辑角色 :param request: :param pk: 要修改的角色id :return: ''' user_obj = models.UserInfo.objects.filter(pk=pk).first() if not user_obj: return HttpResponse("用户不存在") if request.method == "POST": forms = UpdateUserInfoModelForm(instance=user_obj, data=request.POST) if forms.is_valid(): forms.save() return redirect(reverse("rbac:user_list")) else: return render(request, "rbac/change.html", {"forms": forms}) forms = UpdateUserInfoModelForm(instance=user_obj) # 将查询出来的对象交给form组件, 进行渲染。 return render(request, "rbac/change.html", {"forms": forms}) def user_del(request, pk): ''' 删除操作, 需要给与用户提示。 :param reuqest: :param pk: 要删除的角色id :return: ''' origin_url = reverse("rbac:user_list") role_queryset = models.UserInfo.objects.filter(pk=pk) if not role_queryset: return HttpResponse("角色不存在") if request.method == "POST": role_queryset.delete() return redirect(origin_url) return render(request, "rbac/role_del.html", {"cancel": origin_url}) def reset_pwd(request, pk): ''' 重置密码 :param request: :param pk: :return: ''' user_obj = models.UserInfo.objects.filter(pk=pk).first() if not user_obj: return HttpResponse("用户不存在") if request.method == "POST": forms = ResetPasswordUserInfoModelForm(instance=user_obj, data=request.POST) if forms.is_valid(): forms.save() return redirect(reverse("rbac:user_list")) else: return render(request, "rbac/change.html", {"forms": forms}) forms = ResetPasswordUserInfoModelForm() return render(request, "rbac/change.html", {"forms": forms})
模板部分,只有展示列表,是不相同的, 其他的 添加编辑, 删除。 都是使用同一套页面:
{% extends "layout.html" %} {% block content %} <div class="luffy-container"> <div class="btn-group" style="margin: 5px 0"> <a class="btn btn-default" href="{% url 'rbac:user_add' %}"> <i class="fa fa-plus-square" aria-hidden="true"></i> 添加用户 </a> </div> <table class="table table-bordered table-hover"> <thead> <tr> <th>序号</th> <th>ID</th> <th>用户名</th> <th>邮箱</th> <th>重置密码</th> <th>选项</th> </tr> </thead> <tbody> {% for user in user_queryset %} <tr> <td>{{ forloop.counter }}</td> <td>{{ user.id }}</td> <td>{{ user.name }}</td> <td>{{ user.email }}</td> <td><a href="{% url 'rbac:reset_pwd' pk=user.id %}">重置密码</a></td> <td> <a style="color: #333333;" href="{% url 'rbac:user_edit' pk=user.id %}"> <i class="fa fa-edit" aria-hidden="true"></i></a> <a style="color: #d9534f;" href="{% url 'rbac:user_del' pk=user.id %}"><i class="fa fa-trash-o"></i></a> </td> </tr> {% endfor %} </tbody> </table> </div> {% endblock %}
总结:
- Model Form
- 字段的自定制, 添加数据库字段没有的,额外字段。 并进行统一的验证。
- 局部钩子的方法,用于对某一个字段, 进行二次校验。
- 错误提示:
- 手动修改,使用 error_messages = {.......} , 每个字段进行添加。
- settings 中修改配置文件: LANGUAGE_CODE = 'zh-hans' 使django中form组件的英文提示全部变成中文
- 重写__init__方法, 统一给所有的字段添加属性 (class="form-control")
UserInfoModelForm