用户管理示例图:
第一步:路由的创建
rbac/urls.py
from django.urls import re_path from rbac.views import role from rbac.views import user urlpatterns = [ # 角色管理 re_path(r'^role/list/$', role.role_list, name="role_list"), re_path(r'^role/add/$', role.role_add, name="role_add"), re_path(r'^role/edit/(?P<pk>\d+)/$', role.role_edit, name="role_edit"), re_path(r'^role/del/(?P<pk>\d+)/$', role.role_del, name="role_del"), # 用户管理 re_path(r'^user/list/$', user.user_list, name="user_list"), re_path(r'^user/add/$', user.user_add, name="user_add"), re_path(r'^user/edit/(?P<pk>\d+)/$', user.user_edit, name="user_edit"), re_path(r'^user/del/(?P<pk>\d+)/$', user.user_del, name="user_del"), re_path(r'^user/reset/password/(?P<pk>\d+)/$', user.user_reset_pwd, name="user_reset_pwd"), ]
第二步:ModelForm的书写
rbac/forms/user.py
from django import forms from rbac import models from django.core.exceptions import ValidationError class UserModelForm(forms.ModelForm): """添加用户""" confirm_password = forms.CharField( label="确认密码", ) # model中没有的字段,可自行添加一个该字段 class Meta: model = models.Userinfo # 关联的表 fields = ["name", "email", "password", "confirm_password"] # 字段 # 错误提示改为中文的第一种方法 # error_messages = { # "name": {"required": "用户名不能为空"}, # "email": {"required": "邮箱不能为空"}, # "password": {"required": "密码不能为空"}, # "confirm_password": {"required": "确认密码不能为空"}, # 无效 # } # 错误提示改为中文的第二种方法(在settings.py中把LANGUAGE_CODE进行修改) # LANGUAGE_CODE = 'zh-hans' def __init__(self, *args, **kwargs): """为所有字段添加样式""" super(UserModelForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): # name就是上面fields中的字段 field.widget.attrs["class"] = "form-control" def clean_confirm_password(self): """局部钩子函数,校验两次密码是否一致""" password = self.cleaned_data.get("password") confirm_password = self.cleaned_data.get("confirm_password") if password != confirm_password: raise ValidationError("两次密码输入不一致...") return confirm_password class UpdateUserModelForm(forms.ModelForm): """编辑用户""" class Meta: model = models.Userinfo fields = ["name", "email"] def __init__(self, *args, **kwargs): super(UpdateUserModelForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs["class"] = "form-control" class ResetPasswordUserModelForm(forms.ModelForm): """重置密码""" confirm_password = forms.CharField( label="确认密码", ) class Meta: model = models.Userinfo fields = ["password", "confirm_password"] def __init__(self, *args, **kwargs): super(ResetPasswordUserModelForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs["class"] = "form-control" def clean_confirm_password(self): password = self.cleaned_data.get("password") confirm_password = self.cleaned_data.get("confirm_password") if password != confirm_password: raise ValidationError("两次密码输入不一致...") return confirm_password
第三步:视图函数的书写
rbac/views/user.py
"""角色管理""" from rbac import models from django.shortcuts import render, redirect, HttpResponse from django.urls import reverse from rbac.forms.user import UserModelForm, UpdateUserModelForm, ResetPasswordUserModelForm def user_list(request): """ 用户列表 :param request: :return: """ user_queryset = models.Userinfo.objects.all().order_by("pk") return render(request, "rbac/user_list.html", {"users": user_queryset}) def user_add(request): """ 添加用户 :param request: :return: """ if request.method == "GET": form = UserModelForm() return render(request, "rbac/change.html", {"form": form}) form = UserModelForm(data=request.POST) # 保存 if form.is_valid(): form.save() return redirect(reverse("rbac:user_list")) return render(request, "rbac/change.html", {"form": form}) def user_edit(request, pk): """ 用户编辑 :param request: :param pk: 要修改的用户ID :return: """ obj = models.Userinfo.objects.filter(id=pk).first() if not obj: return HttpResponse("用户不存在...") if request.method == "GET": form = UpdateUserModelForm(instance=obj) # 将原有的数据展示 return render(request, "rbac/change.html", {"form": form}) form = UpdateUserModelForm(instance=obj, data=request.POST) # 保存编辑后的数据 if form.is_valid(): form.save() return redirect(reverse("rbac:user_list")) return render(request, "rbac/change.html", {"form": form}) def user_del(request, pk): """ 删除用户 :param request: :param pk: :return: """ origin_url = reverse("rbac:user_list") if request.method == "GET": return render(request, "rbac/delete.html", {"cancel_url": origin_url}) models.Userinfo.objects.filter(id=pk).delete() return redirect(origin_url) def user_reset_pwd(request, pk): """ 重置密码 :param request: :param pk: :return: """ obj = models.Userinfo.objects.filter(id=pk).first() if not obj: return HttpResponse("用户不存在...") if request.method == "GET": form = ResetPasswordUserModelForm() # 重置密码,不需要把之前的密码进行展示 return render(request, "rbac/change.html", {"form": form}) form = ResetPasswordUserModelForm(instance=obj, data=request.POST) # 保存编辑后的数据 if form.is_valid(): form.save() return redirect(reverse("rbac:user_list")) return render(request, "rbac/change.html", {"form": form})
第四步:模板的创建(change.html和delete.html都是共用的,所以只需要创建一个展示用户的html即可)
rbac/templates/rbac/user_list.html
{% 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>用户名</th> <th>邮箱</th> <th>重置密码</th> <th>操作</th> </tr> </thead> <tbody> {% for row in users %} <tr> <td>{{ forloop.counter }}</td> <td>{{ row.name }}</td> <td>{{ row.email }}</td> <td> <a href="{% url 'rbac:user_reset_pwd' pk=row.id %}">重置密码</a> </td> <td> <a style="color: #333333;" href="{% url 'rbac:user_edit' pk=row.id %}"> <i class="fa fa-edit" aria-hidden="true"></i></a> <a style="color: #d9534f;" href="{% url 'rbac:user_del' pk=row.id %}"> <i class="fa fa-trash-o"></i> </a> </td> </tr> {% endfor %} </tbody> </table> </div> {% endblock %}
知识点:
- ModelForm
- 字段的自定制
- 钩子函数
- 错误提示变成中文的两种方法
- 重写__init__方法,统一给所有字段添加属性("form-control")
- 根据namespace和name反向生成URL
- 模板的查找顺序